列表

详情


NC20239. [SCOI2003]蜘蛛难题

描述

有一堆管道,还有一个蜘蛛Willy,如下图所示。所有管道的是上端开口,下端封底,直径都是1cm,连接两个管道的连接容量无限,但体积可以忽略不计。
 
在第一个管道上方有一个水源,从中有水不断往下流,速度为每秒0.25 cm3。由于管道横截面积为0.25 cm3,所以单给一个管道注水时水面每秒上升1cm。
根据物理知识,在前2秒中,水注如左边的管道底部,第3~5秒时注入右边的管道,第6~9秒同时注入两个管道(虽然流量不变,但是由于同时给两个管道注水,因此水面上升的速度仅为每秒0.5cm),接触到蜘蛛。 
给出管道和管道之间连接的位置,以及蜘蛛Willy的位置,求水面接触到Willy的时间。
假设蜘蛛的实际位置比给出的略高一点,因此如果蜘蛛在左边管道的n=4的位置,答案应该是5秒。因为前两秒后水面虽然看起来接触到了Willy,但实际上比Willy略低一点。

输入描述

所有位置都用有序数对(x, y)表示,其中y坐标从上到下逐渐增大;x坐标从左到右逐渐增大,因此左上角的坐标为(0,0),其他所有坐标值为0到100之间的整数。
输入第一行为一个整数p(1 ≤ p ≤ 20),表示管道的数目;
以下p行,每行用x, y, h三个整数描述一根管道。(x,y)为管道左上角坐标;h为管道高度(1 ≤ h ≤ 20)。
以下一行为一个整数L(0 ≤ L ≤ 50),为连接的个数。
以下L行每行用三个整数x, y, d描述一个连接,(x,y)为左端点的坐标,d为连接的长度(1 ≤ d ≤ 20)。
最后一行为两个整数a, b,表示Willy在管道a的y坐标为b的位置。
管道按照在文件中出现的顺序编号为1,2,3…p 以下为一些假设:
水源总是在第一根管道的正上方
连接不会穿越管道
任意两个连接的y坐标都不相同
任意两个管道的左上角的x坐标都不相同
任意连接的两个端点都在管道上(不会出现悬空的情形)

输出描述

仅一个整数,为水面接触到Willy的时间。如果水面无法接触到Willy,输出-1。

示例1

输入:

2
2 0 6
5 1 6
1
3 4 2
2 2

输出:

9

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

Java 解法, 执行用时: 15ms, 内存消耗: 9540K, 提交时间: 2023-07-28 20:32:59

import java.io.*;
import java.math.*;
import java.util.*;

/*
 * Author: Atuer
 */

public class Main
{
	// ==== Solve Code ====//
	static int INF = 1000000010;

	public static void csh()
	{

	}

	public static void main(String[] args) throws IOException
	{
		csh();

		int t = 1;
		while (t-- > 0)
		{
			solve();
			out.flush();
		}

		out.close();
	}

	static int maxn = 25, maxm = 55;
	static int[] h = new int[maxn];
	// 长度 = 水能否满足往对应方向流的值
	static int[] nex = new int[maxm], des = new int[maxm], len = new int[maxm];
	static int idx = 1;

	public static void add(int a, int b, int c)
	{
		des[idx] = b;
		len[idx] = c;
		nex[idx] = h[a];
		h[a] = idx++;
	}

	public static void solve()
	{
		int n = in.nextInt();
		TreeMap<Integer, Integer> lsh = new TreeMap<>();
		int[] up = new int[n + 1], down = new int[n + 1];
		// 离散化存入所有桶的信息(up桶高,down水面)
		for (int i = 1; i <= n; i++)
		{
			lsh.put(in.nextInt(), i);
			up[i] = in.nextInt();
			down[i] = up[i] + in.nextInt();
		}

		int m = in.nextInt();
		for (int i = 1; i <= m; i++)
		{
			int x = in.nextInt();
			int y = in.nextInt();
			int d = in.nextInt();
			add(lsh.get(x - 1), lsh.get(x + d), y);
			add(lsh.get(x + d), lsh.get(x - 1), y);
		}

		int zx = in.nextInt();
		int zy = in.nextInt();
		int t = 0;
		s: while (true)
		{
			Queue<Integer> q = new LinkedList<Integer>();
			boolean[] can = new boolean[n + 1];
			can[1] = true;
			q.add(1);

			// 若该桶可流,则查找该桶可以流向的桶
			while (!q.isEmpty())
			{
				int p = q.poll();

				for (int j = h[p]; j != 0; j = nex[j])
				{
//					out.println(p + ">" + des[j] + ":" + len[j]);
					if (!can[des[j]] && down[p] <= len[j])
					{
						can[des[j]] = true;
						q.add(des[j]);
					}
				}

			}

			// 最低水面
			int max = 0;
			for (int i = 1; i <= n; i++)
				if (can[i])
					max = Math.max(down[i], max);

			// 蜘蛛能被淹到且可以被淹
			if (can[zx] && zy == max)
			{
				out.println(t);
				return;
			}

			// 水面溢出 (当前桶流通且水装满且是最低水面的桶)
			for (int i = 1; i <= n; i++)
				if (can[i] && down[i] == up[i] && down[i] == max)
					break s;

			// 查找最低水面
			for (int i = 1; i <= n; i++)
				if (can[i] && down[i] == max)
				{
					down[i]--;
					t++;
				}

//			out.println(t);
//			out.println(Arrays.toString(up));
//			out.println(Arrays.toString(down));

		}

		out.println(-1);
	}

	public static class Node implements Comparable<Node>
	{
		// last candrop
		int x, y;

		public Node(int x, int y)
		{
			this.x = x;
			this.y = y;
		}

		public String toString()
		{
			return this.x + " " + this.y;
		}

		@Override
		public int compareTo(Node o)
		{
			return (this.x + this.y) - (o.x + o.y);
		}

	}
	// ==== Solve Code ====//

	// ==== Template ==== //
	public static long cnm(int a, int b)
	{
		long sum = 1;
		int i = a, j = 1;
		while (j <= b)
		{
			sum = sum * i / j;
			i--;
			j++;
		}
		return sum;
	}

	public static int gcd(int a, int b)
	{
		return b == 0 ? a : gcd(b, a % b);
	}

	public static int lcm(int a, int b)
	{
		return (a * b) / gcd(a, b);
	}

	public static void gbSort(long[] a, int l, int r)
	{
		if (l < r)
		{
			int m = (l + r) >> 1;
			gbSort(a, l, m);
			gbSort(a, m + 1, r);

			long[] t = new long[r - l + 1];
			int idx = 0, i = l, j = m + 1;

			while (i <= m && j <= r)
				if (a[i] <= a[j])
					t[idx++] = a[i++];
				else
					t[idx++] = a[j++];

			while (i <= m)
				t[idx++] = a[i++];
			while (j <= r)
				t[idx++] = a[j++];

			for (int z = 0; z < t.length; z++)
				a[l + z] = t[z];
		}
	}
	// ==== Template ==== //

	// ==== IO ==== //
	static InputStream inputStream = System.in;
	static InputReader in = new InputReader(inputStream);
	static PrintWriter out = new PrintWriter(System.out);

	static class InputReader
	{
		public BufferedReader reader;
		public StringTokenizer tokenizer;

		public InputReader(InputStream stream)
		{
			reader = new BufferedReader(new InputStreamReader(stream), 32768);
			tokenizer = null;
		}

		public String next()
		{
			while (tokenizer == null || !tokenizer.hasMoreTokens())
			{
				try
				{
					tokenizer = new StringTokenizer(reader.readLine());
				} catch (IOException e)
				{
					throw new RuntimeException(e);
				}
			}
			return tokenizer.nextToken();
		}

		boolean hasNext()
		{
			while (tokenizer == null || !tokenizer.hasMoreTokens())
			{
				try
				{
					tokenizer = new StringTokenizer(reader.readLine());
				} catch (Exception e)
				{
					return false;
					// TODO: handle exception
				}
			}
			return true;
		}

		public String nextLine()
		{
			String str = null;
			try
			{
				str = reader.readLine();
			} catch (IOException e)
			{
				e.printStackTrace();
			}
			return str;
		}

		public int nextInt()
		{
			return Integer.parseInt(next());
		}

		public long nextLong()
		{
			return Long.parseLong(next());
		}

		public Double nextDouble()
		{
			return Double.parseDouble(next());
		}

		public BigInteger nextBigInteger()
		{
			return new BigInteger(next());
		}

		public BigDecimal nextBigDecimal()
		{
			return new BigDecimal(next());
		}
	}
	// ==== IO ==== //
}

C++(clang++ 11.0.1) 解法, 执行用时: 3ms, 内存消耗: 424K, 提交时间: 2023-07-26 14:29:32

#include <bits/stdc++.h>
using namespace std;

int n,t,m;
struct node
{
	int x,y,h;
};
int sz[205];
int xx[205];
node a[205];
int lj[205][205];
bool vis[205];

struct edge
{
	int v,y;
};
vector<edge> e[205];


void solve()
{
	cin>>n;
	for(int i=1; i<=n; i++)
	{
		sz[i]=i;
		cin>>a[i].x>>a[i].y>>a[i].h;
		a[i].h=a[i].h+a[i].y;
		xx[a[i].x]=i;
	}
	cin>>m;
	for(int i=1; i<=m; i++)
	{
		int x,y,z;
		cin>>x>>y>>z;
		int u=xx[x-1];
		int v=xx[x+z];
		e[u].push_back({v,y});
		e[v].push_back({u,y});
	}
	int A,B;
	cin>>A>>B;
	vis[1]=true;
	int ans=0;
	while(1)
	{
		for(int i=1; i<=n; i++)
		{
			if(vis[i])
			{
				for(int j=0; j<e[i].size(); j++)
				{
					int v=e[i][j].v;
					int h=e[i][j].y;
//					cout<<i<<" "<<v<<" "<<h<<"\n";
					if(a[i].h<=h&&!vis[v])
					{
						vis[v]=true;
					}
				}
			}
		}
		int mn=0;
		for(int i=1; i<=n; i++)
		{
			if(vis[i])
			{
				mn=max(mn,a[i].h);
			}
		}
		if(vis[A]&&mn==B)
		{
			cout<<ans<<"\n";
			return;
		}
		for(int i=1; i<=n; i++)
		{
			if(vis[i]&&a[i].h==a[i].y&&a[i].y==mn)
			{
				cout<<"-1\n";
				return;
			}
		}
		for(int i=1; i<=n; i++)
		{
			if(vis[i]&&a[i].h==mn)
			{
				a[i].h--;
				ans++;
//				cout<<i<<" "<<ans<<" "<<mn<<"\n";
			}
		}
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int cnt=0;
	int tn=1;
	while(tn--)
	{
		solve();
	}
}

上一题