uva--301+dfs回溯穷举
来源:互联网 发布:特朗普穆斯林禁令知乎 编辑:程序博客网 时间:2024/06/05 04:59
题意:
一列火车有n个座位,它的行驶路线上有m个售票站,对于每个售票站售出的火车票,可以选择全部接受或者全部不接受;每张火车票的价格
为起点与终点站之间的站数差;问这样选择售票站才能使收益最大?
思路:
显然对于每个售票站,都可以选择接受其所有票或者不接受;m<=22 所以可以用dfs穷举所有的方案。具体是:先按起点站对所有售票站按升序排序,用cnt记录当前火车上的人数,sum记录当前的收入,cur记录当前要判断的售票站的编号,vis[]记录每一站应该下车的人数;对于每一个售票站如果满足要求,就可以选择,当然也可以不选,对于其它情况都是不用选择,如此进行dfs。当然这里的重点在于判断当前的售票站是否满足要求,一种方法就是不在每一站对下车的情况进行处理而是通过用cnt-该站之前应该下车的人数是否大于n进行判断;另一种方法是,每一次不管选不选择售票站都对下车的情况进行处理,每次只关注此次的起点站和上次的起点站,这样可以避免重复处理。
反思:
在这种dfs穷举的题目中,进行判断时判断的方式一定也要是可以递归回溯的,否则判断就会出错,比如下面的第三份代码,判断完后直接赋0,就会导致回溯的时候出错。
代码如下:
#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>using namespace std;int ans,vis[10],m,total,n;typedef struct{ int x,y; int cnt;}P;P p[30];int cmp(P p1,P p2){ if(p1.x==p2.x) return p1.y<p2.y; return p1.x<p2.x;}int check(int cur,int cnt){ int sum=0,i; for(i=0;i<=p[cur].x;i++) sum+=vis[i]; if(cnt-sum+p[cur].cnt<=total) return 1; return 0;}void dfs(int cur,int sum,int cnt){ int j; if(cur==m) { if(ans<sum) ans=sum; return ; } if((check(cur,cnt))) { vis[p[cur].y]+=p[cur].cnt; dfs(cur+1,sum+p[cur].cnt*(p[cur].y-p[cur].x),cnt+p[cur].cnt); vis[p[cur].y]-=p[cur].cnt; } dfs(cur+1,sum,cnt);}int main(){ int i,j; while(scanf("%d%d%d",&total,&n,&m)) { if(total==0&&n==0&&m==0) break; for(i=0;i<m;i++) { scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].cnt); } sort(p,p+m,cmp); ans=0; memset(vis,0,sizeof(vis)); dfs(0,0,0); printf("%d\n",ans); } return 0;}
代码2:
#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>using namespace std;int ans,vis[10],m,total,n;typedef struct{ int x,y; int cnt;}P;P p[30],p1;int cmp(P p1,P p2){ if(p1.x==p2.x) return p1.y<p2.y; return p1.x<p2.x;}void dfs(int cur,int sum,int cnt,int pre){ int j; if(cur==m) { if(ans<sum) ans=sum; return ; } //无论这个车站上不上人,下车都是必须的 for(j=pre+1;j<=p[cur].x;j++) cnt-=vis[j]; if(cnt+p[cur].cnt<=total) { vis[p[cur].y]+=p[cur].cnt; dfs(cur+1,sum+p[cur].cnt*(p[cur].y-p[cur].x),cnt+p[cur].cnt,p[cur].x); vis[p[cur].y]-=p[cur].cnt; } dfs(cur+1,sum,cnt,p[cur].x);}int main(){ int i,j; while(scanf("%d%d%d",&total,&n,&m)) { if(total==0&&n==0&&m==0) break; for(i=0;i<m;i++) { scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].cnt); } sort(p,p+m,cmp); ans=0; memset(vis,0,sizeof(vis)); dfs(0,0,0,0); printf("%d\n",ans); } return 0;}
错误代码:
#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>using namespace std;int ans,vis[10],m,total,n;typedef struct{ int x,y; int cnt;}P;P p[30],p1;int cmp(P p1,P p2){ if(p1.x==p2.x) return p1.y<p2.y; return p1.x<p2.x;}void dfs(int cur,int sum,int cnt){ int j; if(cur==m) { if(ans<sum) ans=sum; return ; } //无论这个车站上不上人,下车都是必须的 //下车之后记得将相应车站人数清0 for(j=0;j<=p[cur].x;j++) { cnt-=vis[j]; vis[j]=0;//赋0操作导致回溯出错 } if(cnt+p[cur].cnt<=total) { vis[p[cur].y]+=p[cur].cnt; dfs(cur+1,sum+p[cur].cnt*(p[cur].y-p[cur].x),cnt+p[cur].cnt); vis[p[cur].y]-=p[cur].cnt; } dfs(cur+1,sum,cnt);}int main(){ int i,j; while(scanf("%d%d%d",&total,&n,&m)) { if(total==0&&n==0&&m==0) break; for(i=0;i<m;i++) { scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].cnt); } sort(p,p+m,cmp); ans=0; memset(vis,0,sizeof(vis)); dfs(0,0,0); printf("%d\n",ans); } return 0;}
0 0
- uva--301+dfs回溯穷举
- UVA 301 POJ 1040- Transportation DFS 回溯
- uva--729+dfs回溯
- uva--639+dfs+回溯
- uva--10334+dfs+回溯
- uva--331+dfs+回溯
- uva--208+dfs+回溯
- uva--10400+dfs+回溯
- UVA 225 - Golygons(dfs回溯)
- uva 11218 KTV(DFS+回溯)
- dfs穷举
- UVA 331 Mapping the Swaps (回溯+dfs)
- [UVA 307] Sticks (DFS回溯 + 剪枝)
- The Settlers of Catan uva dfs+回溯
- 【UVA】10318-Security Panel(DFS 回溯)
- UVa 140 Bandwidth(DFS 回溯 剪枝)
- UVa 225 - Golygons(DFS+回溯)
- UVA Getting in Line (DFS回溯)
- MySQL使用AUTO_INCREMENT列的表注意事项之delete数据篇
- 昆仑叶哲华:如何完善品牌管理
- ninth(求y2(switch))
- php开源产品
- redis学习笔记5,lists类型
- uva--301+dfs回溯穷举
- ArcGIS API for Javascript 第一个地图
- 权重比PR更吸引站长的眼球?
- java 打印各种 图形
- MySQL复制表数据到新表的方法
- jar命令成功完成 java -jar 命令却提示“没有主清单属性”!
- 简单例子:C++多态
- DELPHI使用IDHTTP操作WEB
- WAVE文件格式剖析