UVA - 10537 The Toll! Revisited

题意:

把一批货物从图上一个点运送到另外一个点,图是一个无向图,点有2种类型,一种是农村小写字母表示,一种是城市,大写字母表示,路过农村需要缴纳1个货物的过路费,路过城市每20个货物需要缴纳1货物的过路费,向上取整。

问:最少从起点开始运多少多物,才能到终点有满足要求的数量的货物,输出路径,有多个情况,输出字典序最小。

做法:

反向最短路。

坑点:

1.这个点有10000个货物,上一个点不是有10500个货而是10527的货

2.字典序,不是大小写不区分的,而是严格按ASCII码来

3.由于是反向,向前推时,是看这个点是农村还是城市

反思:

1.数学方面还是不细心

2.在题中没有特别指明的请况下,排字典序不区分大小写,画蛇添足,浪费时间。

代码:

  1 #include<iostream>
  2 using namespace std;
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<cmath>
  7 #include<queue>
  8 typedef long long LL;
  9 struct teamdata{
 10     LL num;
 11     int wz;
 12     bool operator<(const teamdata& pt)const{
 13         if (this->num!=pt.num)
 14         return this->num>pt.num;
 15         else{
 16             char t=pt.wz,s=this->wz;
 17             return s>t;
 18         }
 19     }
 20 };
 21 priority_queue<teamdata> team;
 22 int n,m,l;
 23 int maps[1000][1000];
 24 void init(){
 25     memset(maps,0,sizeof(maps));
 26 }
 27 int trans(char p){
 28     if (p>='a'&&p<='z'){
 29         return p-'a'+26;
 30     }
 31     else if (p>='A'&&p<='Z'){
 32         return p-'A';
 33     }
 34     else
 35     return -1;
 36 }
 37 char s[30];
 38 void getstring(int &st){
 39     char a;
 40     scanf("%s",s);
 41     a=s[0];
 42     st=trans(a);
 43 }
 44 int ii=0;
 45 bool v[1000];
 46 const LL inf=0x7fffffffffff;
 47 LL d[1000];
 48 int pre[1000];
 49 void bfs(int s,int t,LL w){
 50     while(!team.empty()) team.pop();
 51     teamdata pt,pd;
 52     for (int i=0;i<100;i++){
 53         d[i]=inf;v[i]=0;pre[i]=-1;
 54     }
 55     LL ans=-1;
 56     d[s]=w;pt.num=w;pt.wz=s;team.push(pt);
 57     while(!team.empty()){
 58         pt=team.top();team.pop();
 59         if (pt.num>d[pt.wz]) continue;
 60         v[pt.wz]=1;
 61         if (pt.wz==t){
 62             ans=pt.num;break;
 63         }
 64         for (int i=0;i<52;i++){
 65             if (v[i]||!maps[pt.wz][i]) continue;
 66             LL zz=0;
 67             if (pt.wz>=0&&pt.wz<26){
 68                 double ss;
 69                 ss=(double)pt.num*20.0/19.0;
 70                 zz=ceil(ss);
 71                 zz=zz-pt.num;
 72             }
 73             else{
 74                 zz=1;
 75             }
 76             if (d[i]>pt.num+zz){
 77                 d[i]=pt.num+zz;pd.num=d[i];pd.wz=i;
 78                 team.push(pd);pre[i]=pt.wz;
 79             }
 80             else
 81             if (d[i]==pt.num+zz){
 82                 int s=pt.wz,t=pre[i];
 83                 if (s<t){
 84                 d[i]=pt.num+zz;pd.num=d[i];pd.wz=i;
 85                 team.push(pd);pre[i]=pt.wz;
 86                 }
 87             }
 88         }
 89     }
 90     printf("Case %d:\n",ii);
 91     printf("%lld\n",ans);
 92     int x=t;
 93     while(x>=0){
 94     char c;
 95     if(x<26) c='A'+x;
 96     else c='a'+(x-26);
 97     printf("%c",c);
 98     x=pre[x];
 99     if (x>=0) printf("-");
100     }
101     printf("\n");
102 }
103 void deal(){
104     int s,t;
105     init();
106     for (int i=1;i<=n;i++){
107     getstring(s);getstring(t);
108     maps[s][t]=maps[t][s]=1;
109     }
110     LL cs;
111     scanf("%lld",&cs);
112     getstring(s);getstring(t);
113     bfs(t,s,cs);
114 }
115 int main(){
116     while(scanf("%d",&n)!=EOF&&n>=0){
117         ii++;
118         deal();
119     }
120     return 0;
121 }
122 
123 /*
124 x-x/20=y;
125 x*(19/20)=y;
126 x=y*(20/19);
127 */

 

转载于:https://www.cnblogs.com/xfww/p/7623584.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值