题意
运送货物需要缴纳过路费,进入一个村庄需要缴纳1个单位的货物,而进入一个城镇时,每20个单位的货物中就要上缴1个单位(向上取整)。你的任务时已知运送到终点的货物数量,求出初始时所需要的最少货物,以及缴纳货物数量最少的路径。
题解
既然已知了终点的货物,那么就可以从终点按照Dijkstra的思想推向起点。对于城镇的货物的计算办法是ceil(d[x]*20/19.0
。
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100;
const long long INF = 1ll<<60;
typedef long long ll;
typedef pair<ll,int> pii;
int f(char ch) {
if('A' <= ch && ch <= 'Z')
return ch-'A';
else return ch-'a'+26;
}
char g(int ch) {
if(0 <= ch && ch < 26)
return ch+'A';
else
return ch-26+'a';
}
vector<int> G[maxn];
int n,path[maxn];
ll d[maxn];
int S,E;
ll good;
void add(int u,int v) {
G[u].push_back(v);
}
void solve() {
for(int i = 0; i < 52; ++i)
d[i] = INF;
memset(path,-1,sizeof path);
d[E] = good;
priority_queue< pii, vector<pii>, greater<pii> > que;
que.push(pii(d[E],E));
while(!que.empty()) {
pii u = que.top();
que.pop();
if(d[u.second] < u.first)
continue;
int x = u.second;
for(int i = 0; i < G[x].size(); ++i) {
int to = G[x][i];
if(x < 26) { // 城镇
ll v = ceil(d[x]*20/19.0);
if(d[to] > v) {
d[to] = v;
path[to] = x;
que.push(pii(d[to],to));
}
}else {
ll v = d[x]+1;
if(d[to] > v) {
d[to] = v;
path[to] = x;
que.push(pii(d[to],to));
}
}
}
}
}
int main() {
int kas = 1;
// cout << INF << endl;
while(scanf("%d", &n) && (n != -1)) {
for(int i = 0; i < 52; ++i)
G[i].clear();
char a,b;
for(int i = 0; i < n; ++i) {
scanf(" %c %c", &a,&b);
// cout << a << " " << b << endl;
add(f(a),f(b));
add(f(b),f(a));
}
for(int i = 0; i < 52; ++i)
sort(G[i].begin(), G[i].end());
scanf("%d", &good);
scanf(" %c %c", &a,&b);
S = f(a); E = f(b);
solve();
printf("Case %d:\n%lld\n", kas++, d[S]);
vector<char> v;
int x = S;
while(x != -1) {
v.push_back(g(x));
x = path[x];
}
for(int i = 0; i < v.size(); ++i) {
if(i == 0)
printf("%c",v[i]);
else
printf("-%c",v[i]);
}
puts("");
}
return 0;
}