UVA1027 Toll

Description

给定一张无向图,每个节点用 A \(\sim\) Za \(\sim\) z 表示,所有大写字母均为城镇,所有小写字母均为村庄。

经过每个城镇或村庄均要收税,进入那个点便收税,出来不用收税(所以起点是不用收费的)。

城镇是每运送 \(20\) 件货物便收 \(1\) 件货物的税(最后若不足 \(20\) 件的话按 \(20\) 件算)。

村庄是无论多少货物,只需要收 \(1\) 件货物的税即可。

你现在要运送一些货物从 \(S\)\(T\),要求到达 \(T\) 时需要至少剩下 \(p\) 件货物。

问从 \(S\) 出发时最少携带多少货物才能满足要求,有多组测试数据。

Solution

对于字符的点我们很难处理,所以一开始要把所有字符转为数字,文中使用的方法是直接 ASCII 码转换。

发现起点的答案未知,但是终点答案已知,所以可以通过终点反推起点,考虑从终点开始,向起点计算。

初值为 \(dis[T] = p\),类似与求最短路(dijkstra)的算法,把城镇和村庄分开处理

  • 如果是村庄,那直接把边权视作 \(1\),更新即可。

  • 如果是城镇,考虑二分答案,二分从上一个点最少要带多少货物过来即可。

答案即为 \(dis[S]\)

注意,这题虽然点个数不多,但不能使用floyd算法做,因为floyd是基于dp的松弛做法,但是这题的边权并不是固定的,会变化,所以会错。

Code

注意题中输出格式的特殊要求。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#define rep(_, __, ___) for(int _ = __; _ <= ___; _++)
#define per(_, __, ___) for(int _ = __; _ >= ___; _--)
using namespace std;
const int N = 205;
int n;
vector <int> g[N];
int dis[N], b[N], T;
int tar;
char ch1, ch2;
int s, t;
priority_queue <pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > que;
bool ok(int midd, int xx)
{
	int res;
	if(midd % 20 == 0)
	{
		res = midd / 20;
	}
	else
	{
		res = midd / 20 + 1; 
	}
	return (midd - res) >= xx; 
}
void dijkstra()
{
	dis[t] = tar;
	que.push(make_pair(tar, t));
	while(!que.empty())
	{
		int k = que.top().second;
		que.pop();
		if(b[k]) continue;
		b[k] = 1;
		for(int i = 0; i < g[k].size(); i++)
		{
			int v = g[k][i];
			if(b[v]) continue;
			if('A' <= char(k + 'A' - 1) && char(k + 'A' - 1) <= 'Z')//如果该点是城镇,则就按城镇的方法更新接下来的点
			{
				int temp;
				int low = dis[k], high = 1000000;//这里high的取值还能再小一点
				while(low <= high)//二分
				{
					int mid = (low + high) / 2;
					if(ok(mid, dis[k]))
					{
						high = mid - 1;
						temp = mid;
					}
					else
					{
						low = mid + 1;
					}
				}
				if(dis[v] > temp)
				{
					dis[v] = temp;
					que.push(make_pair(dis[v], v));
				}
			}
			else//如果是村庄,就按边权为1的最短路做
			{
				if(dis[v] > dis[k] + 1)
				{
					dis[v] = dis[k] + 1;
					que.push(make_pair(dis[v], v));
				}
			}
		}
	}
}
int main()
{
//	freopen("toll.in", "r", stdin);
//	freopen("toll.out", "w", stdout);
	scanf("%d", &n);
	while(n != -1)
	{
		T++;
		memset(dis, 0x3f, sizeof dis);
		memset(b, 0, sizeof b);
		rep(i, 1, 150)//多测要清空
		{
			g[i].clear();
		}
		for(int i = 1; i <= n; i++)
		{
			cin >> ch1 >> ch2;
			g[ch1 - 'A' + 1].push_back(ch2 - 'A' + 1);
			g[ch2 - 'A' + 1].push_back(ch1 - 'A' + 1);
		}
		cin >> tar >> ch1 >> ch2;
		s = ch1 - 'A' + 1;
		t = ch2 - 'A' + 1;
		dijkstra();
		printf("Case %d: %d\n", T, dis[s]);
		scanf("%d", &n);
	}
	return 0;
}
posted @ 2022-07-16 22:40  panjx  阅读(26)  评论(0)    收藏  举报