DFS系列 POJ(自认为的讲解)
2016-05-08 20:20
381 查看
C - Sum It Up POJ1564
题意:
给你一个N,然后给你一堆数The numbers in each list appear in nonincreasing order, and there may be repetitions.,让你在这对数里找出一些数,如果他们的和sum==N,则按样例的格式数输出。
思路:
那就是DFS呗,深搜一波,当sum==N时就输出,这里有一个就是排除重复的剪枝。为什么呢?
D - 迷宫问题 poj3984
题意:中文…
思路:
这道题推荐BFS+手写队列(这是很重要的)+路径输出,路径输出怎么讲解呢?
(某些非正规定义的词语,是本菜鸡自己定义的)
可以自己模拟一下,在一个队列里,我们用当前元素的pre记录上面那个元素在队列里的节点。最开始我们知道是左上角,所以就初始化他的pre值为-1,最后到了终点,就递归输出。
这里用手写队列不仅跑的飞快而且非常省时间。可以感受一下。
那么我们为什么要用STL的queue呢?知道了,请告诉我!谢谢!(学长说用STL简单方便)
E – Sticks poj1011
题意:给你一堆棒子,这些棒子是你从一堆一样的棒子折断而来的,现在你忘记了是从那一堆一样的棒子的长度,让你写一个程序,求最短的长度
思路:
讲道理这题的思路,好难讲。
DFS也是非常混乱,剪枝也是.。
与其说是找不到这种所谓的强有力的剪枝,不如说是自己思路不够全面。
其实剪枝就是,尽可能地少去运行不必要的相同条件的路。
好吧,还是来谈谈这道题的体会。
我们可以发现因为all parts became at most 50 units long,而且there are at most 64 sticks,那么原始的长度最长也就是320,那么我们就有理由可以尝试枚举长度,然后去判断是否是最小的长度。
我们可以进行排序,从而大大减少递归次数;(倒序)
为什么是倒序,因为棒子越长的话越不灵活;所以我们是有依据采用倒序的
那么出现一个剪枝:这个满足的长度L,一定满足棒子的总和sum%L==0这个条件。
而且我们还可以想到以判除重复的条件剪枝,即在此刻没有条件的话,就没必要再去对这个相同的棒子去DFS。
题意:
给你一个N,然后给你一堆数The numbers in each list appear in nonincreasing order, and there may be repetitions.,让你在这对数里找出一些数,如果他们的和sum==N,则按样例的格式数输出。
思路:
那就是DFS呗,深搜一波,当sum==N时就输出,这里有一个就是排除重复的剪枝。为什么呢?
#include<iostream> #include<cstdio> #include<stdlib.h> #include<vector> #include<string.h> #include<algorithm> using namespace std; typedef long long LL; #define INF 0x3f3f3f3f #define N 1010 int d ; int a ; int n,m; int flag; void dfs(int num,int sum,int v) { if(sum==n) { flag=1; printf("%d",d[0]); for(int i=1;i<num;i++) { printf("+%d",d[i]); } printf("\n"); } if(sum>n) return; for(int i=v;i<m;i++) { d[num]=a[i]; dfs(num+1,sum+a[i],i+1); while(a[i]==a[i+1]&&i<m-1) //判重 i++; } } int main() { while(~scanf("%d%d",&n,&m)&&n&&m) { for(int i=0;i<m;i++) scanf("%d",&a[i]); printf("Sums of %d:\n",n); flag=0; dfs(0,0,0); if(!flag) printf("NONE\n"); } return 0; }
D - 迷宫问题 poj3984
题意:中文…
思路:
这道题推荐BFS+手写队列(这是很重要的)+路径输出,路径输出怎么讲解呢?
(某些非正规定义的词语,是本菜鸡自己定义的)
可以自己模拟一下,在一个队列里,我们用当前元素的pre记录上面那个元素在队列里的节点。最开始我们知道是左上角,所以就初始化他的pre值为-1,最后到了终点,就递归输出。
这里用手写队列不仅跑的飞快而且非常省时间。可以感受一下。
那么我们为什么要用STL的queue呢?知道了,请告诉我!谢谢!(学长说用STL简单方便)
#include<iostream> #include<cstdio> #include<stdlib.h> #include<vector> #include<string.h> #include<algorithm> using namespace std; typedef long long LL; #define INF 0x3f3f3f3f #define N 1010 struct asd{ int x,y; int pre; //用来记录路径 }; asd q[25*10]; int head,tail; int bmap[6][6]; bool vis[6][6]; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; void shuchu(int x) { if(q[x].pre==-1) { printf("(%d, %d)\n",q[x].x,q[x].y); } else { shuchu(q[x].pre); printf("(%d, %d)\n",q[x].x,q[x].y); } } void bfs() { head=0;tail=1; q[head].x=0; q[head].y=0; q[head].pre=-1; memset(vis,0,sizeof(vis)); vis[0][0]=1; while(head<tail) { int bx,by; bx=q[head].x; by=q[head].y; if(bx==4&&by==4) { shuchu(q[head].pre); return; } for(int i=0;i<4;i++) { int aa=bx+dx[i]; int bb=by+dy[i]; if(aa<0||bb<0||aa>4||bb>4||vis[aa][bb]||bmap[aa][bb]) continue; vis[aa][bb]=1; q[tail].pre=head; q[tail].x=aa; q[tail].y=bb; tail++; } head++; } } int main() { for(int i=0;i<5;i++) { for(int j=0;j<5;j++) scanf("%d",&bmap[i][j]); } bfs(); printf("(4, 4)\n"); return 0; }
E – Sticks poj1011
题意:给你一堆棒子,这些棒子是你从一堆一样的棒子折断而来的,现在你忘记了是从那一堆一样的棒子的长度,让你写一个程序,求最短的长度
思路:
讲道理这题的思路,好难讲。
DFS也是非常混乱,剪枝也是.。
与其说是找不到这种所谓的强有力的剪枝,不如说是自己思路不够全面。
其实剪枝就是,尽可能地少去运行不必要的相同条件的路。
好吧,还是来谈谈这道题的体会。
我们可以发现因为all parts became at most 50 units long,而且there are at most 64 sticks,那么原始的长度最长也就是320,那么我们就有理由可以尝试枚举长度,然后去判断是否是最小的长度。
我们可以进行排序,从而大大减少递归次数;(倒序)
为什么是倒序,因为棒子越长的话越不灵活;所以我们是有依据采用倒序的
那么出现一个剪枝:这个满足的长度L,一定满足棒子的总和sum%L==0这个条件。
而且我们还可以想到以判除重复的条件剪枝,即在此刻没有条件的话,就没必要再去对这个相同的棒子去DFS。
#include<iostream> #include<cstdio> #include<stdlib.h> #include<vector> #include<string.h> #include<algorithm> using namespace std; typedef long long LL; #define INF 0x3f3f3f3f #define N 70 int len ; int n; int flag,k; bool vis ; void dfs(int v,int sum,int num) { if(flag) return; if(sum==k) { if(num==n) { flag=1; } else dfs(0,0,num); return; } if(sum==0) { int v=0; while(vis[v]) v++; vis[v]=1; dfs(v+1,len[v],num+1); vis[v]=0; return; } for(int i=v; i<n; i++) { if(sum+len[i]<=k&&!vis[i]) { if(len[i]==len[i-1]&&!vis[i-1]) continue; vis[i]=1; dfs(i+1,sum+len[i],num+1); vis[i]=0; } } } bool cmp(int a,int b) { return a>b; } int main() { int sum; int tmax; while(~scanf("%d",&n)&&n) { sum=0; tmax=-1; for(int i=0; i<n; i++) { scanf("%d",&len[i]); if(tmax<len[i]) tmax=len[i]; sum+=len[i]; } sort(len,len+n,cmp); for(k=tmax; k<=sum; k++) { if(sum%k==0) { flag=0; memset(vis,0,sizeof(vis)); dfs(0,0,0); if(flag) { printf("%d\n",k); break; } } } } return 0; }
相关文章推荐
- JVM学习笔记(一)------基本结构
- Genuino 101无法下载程序的问题
- 最短路水题 HDU 1874畅通工程续
- Armstrong数
- [Modern OpenGL系列(四)]在OpenGL中使用Shader
- 好的个人网站收藏
- 小猫统计:生成视图
- Closest Common Ancestors【POJ1470】——LCA
- Unityads安卓接入
- C++八皇后问题
- 给大一的学弟学妹们培训java web的后台开发讨论班计划
- ArcEngine定义查询
- Xcode界面编辑器 could not insert new outlet connection
- Oracle如何实现多个字段去重
- POJ - 1988 Cube Stacking
- 如何解决了Mac上网速度很慢的问题
- 快速幂+素数 HDU 1905 Pseudoprime numbers
- java容器总结
- Bone Collector
- 从B树、B+树、B*树谈到R 树