原题链接
题目大意:点有城镇和村庄两种,经过城镇时收取身上百分之五的货物的过路费(向上取整),经过村庄时只收取一个单位的过路费,问从某一点出发且到达指定终点时,身上至少携带指定数量的货物,问出发时至少带多少货物。
思路:从终点开始倒推,村庄比较好办,城镇比较麻烦,要解一个含整除的方程,博主使用的是二分法……如果有更好的方法还请指教。详情见代码。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define clr(a,b) memset(a,b,sizeof(a))
#define min(a,b) (a<b?a:b)
const int ss=60;
using namespace std;
typedef long long LL;
char ch[ss];
struct EDGE{
int u,v,next;
}edge[ss*ss];
//得到某一字母的编号
int idx(char c){
if(c>='A'&&c<='Z')return c-'A';
return c-'a'+26;
}
int head[ss],pp;
void addedge(char a,char b){
int u=idx(a),v=idx(b);
edge[++pp]=(EDGE){u,v,head[u]};
head[u]=pp;
}
//某点是否为城镇
bool ist(int u){
return u<26;
}
bool vis[ss];
int g[ss];
LL d[ss];
struct heap{
int id;
LL d;
bool operator<(const heap&a)const{
return d>a.d;
}
};
priority_queue<heap>Q;
void push(int a,LL b){
Q.push((heap){a,b});
}
//解方程 x-((x-1)/20+1)=a,“/”为整除,且如果不是唯一解要取较小解。
LL solve(LL a){
a++;
LL l=0,r=2*a,ret;
while(l<=r){
LL m=l+(r-l)/2;
LL fx=m-(m-1)/20;
if(fx>=a)r=m-1,ret=m;
else l=m+1;
}
return ret;
}
//输出路径
void print(int u){
if(u==-1)return;
printf("-%c",ch[u]);
print(g[u]);
}
void dijkstra(int s,int t,LL tar){
clr(vis,0);
clr(g,-1);
clr(d,100);
d[s]=tar;
push(s,d[s]);
while(!Q.empty()){
heap r=Q.top();Q.pop();
int u=r.id;
if(vis[u])continue;
vis[u]=1;
if(ist(u)){
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].v;
LL a=solve(d[u]);
if(d[v]==a){
g[v]=min(g[v],u);
}
if(d[v]>a){
d[v]=a;
push(v,d[v]);
g[v]=u;
}
}
}else{
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].v;
if(d[v]==d[u]+1){
g[v]=min(g[v],u);
}
if(d[v]>d[u]+1){
d[v]=d[u]+1;
push(v,d[v]);
g[v]=u;
}
}
}
}
cout<<d[t]<<endl;
putchar(ch[t]);
print(g[t]);
puts("");
}
int main(){
freopen("10537.in","r",stdin);
for(char c='A';c<='Z';c++){
ch[(int)c-'A']=c;
}
for(char c='a';c<='z';c++){
ch[(int)c-'a'+26]=c;
}//为字母编号
int m,T=0;
for(;;){
scanf("%d",&m);getchar();
if(m==-1)break;
printf("Case %d:\n",++T);
pp=0;clr(head,0);
while(m--){
char a=getchar();getchar();
char b=getchar();getchar();
addedge(a,b);
addedge(b,a);
}
int t;
scanf("%d",&t);getchar();
char a=getchar();getchar();
char b=getchar();getchar();
dijkstra(idx(b),idx(a),t);
}
return 0;
}