POJ2331 Water Pipe 解题报告
来源:互联网 发布:程序员需要学什么语言 编辑:程序博客网 时间:2024/06/08 12:21
题目意思:
你是一个修水管的工人。在一个1000*1000的坐标系中需要用水管联通两个城市。显然,为了让你的工作变得简单,你的老板决定水管只能横着或者竖着放。有一些不同型号的水管,会告诉你每一种水管的长度和数量。现在你要做的是求出最少能够接通两个城市的水管数量。
输入:
只有一组数据啦啦~~
首先两个数,代表城市1的横纵坐标;
然后再来两个数,代表城市2的横纵坐标;
然后是一个数n,代表有n种型号的水管;
再之后是n个数,代表每种型号水管的长度;
又是n个数,代表每种型号水管的数量。
输出:
最少需要的水管数量;
要是无解,则输出-1。
PS:这个水管是比较有特色的,因为他们可以交叉、重叠。比如,下面两组水管也是合法的:
第一组:
水管1: 1,1 1,2 1,3
水管2: 1,2 2,2 2,3
第二组:
水管1: 1,1 1,2 1,3
水管2: 1,1 1,2
讲不清楚这个特色,大家自己看看这两组水管吧:)
现在开始讲怎么做~~
首先,我们答案无非分为两种:有答案还是没答案;
显然,我们只需要考虑有答案的:
如果起点和终点是同一个点,那么就不需要你修了(答案直接是0);
否则
假设所有水管的数量和为sum;
那么,我们的答案就是在[1,sum]这个区间里了~
for(ans=1;ans<=sum;ans++) if(pd(ans))break;
显然,我们要的只是最少的水管数量。
于是,接下来要用到一种神奇的IDA*算法(具体看代码吧);
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<queue>const int maxn=1010;using namespace std;int sx,sy,ex,ey,n,hx[1010],hy[1010],sum,ans;struct stick{int l,c;}a[20];void bfs(int *h,int x){ queue<int>q;//BFS的队列啊~~ while(!q.empty())q.pop();//以防万一 h[x]=0;//这个点答案为0(所以memset是-1) q.push(x);//显然 while(!q.empty()){ x=q.front(); q.pop(); for(int i=1;i<=n;i++){//枚举每一根木棍 //printf("x:%d lenth:%d\n",x,a[i].l); //这个注释是输出当前木棍的信息 if(x-a[i].l>=1&&h[x-a[i].l]==-1){ //往左走不能出界并且还没算过 h[x-a[i].l]=h[x]+1; //printf("push : %d\n",x-a[i].l); q.push(x-a[i].l); }if(x+a[i].l<=1000&&h[x+a[i].l]==-1){ //往右走 h[x+a[i].l]=h[x]+1; //printf("push : %d\n",x-a[i].l); q.push(x+a[i].l); } } }}bool pd(stick *a,int x,int d,int k){//a数组,坐标,deep,kind(是横坐标还是纵坐标) stick tmp[20]; int hv=k?hy[x]:hx[x];//0是横坐标,1是纵坐标 if(hv==-1||hv+d>ans)return false; //要是没算过,显然不符合条件 if(hv==0){//要是这个答案是0 if(!k)return pd(a,sy,d,1); //讨论纵坐标 else return true; } for(int i=1;i<=n;i++) tmp[i]=a[i];//由于涉及到修改木棍数量,所以要一个临时数组 for(int i=1;i<=n;i++){//依次枚举每类木棍 if(tmp[i].c<=0)continue;//要是没了,下一个 tmp[i].c--;//那么就先用掉 if(x-tmp[i].l>=1)//是往左(下)放? if(pd(tmp,x-tmp[i].l,d+1,k))return true; if(x+tmp[i].l<=1000)//还是往右(上)放? if(pd(tmp,x+tmp[i].l,d+1,k))return true; tmp[i].c++;//要是左右(上下)都不行,乖乖把木棍放回去吧 } return false;}int main(){ int i,j,k;sum=0; scanf("%d%d%d%d%d",&sx,&sy,&ex,&ey,&n); //输入起点终点和水管种类数量 for(i=1;i<=n;i++) scanf("%d",&a[i].l); //输入水管长度 for(i=1;i<=n;i++){ scanf("%d",&a[i].c); sum+=a[i].c; } //每种水管的数量,sum记得累加 if(sx==ex&&sy==ey){puts("0");return 0;}; //要是不用走,那直接 return 0; 就好了 memset(hx,-1,sizeof(hx)); memset(hy,-1,sizeof(hy)); bfs(hx,ex); bfs(hy,ey); //需要这个步骤先算一遍 for(ans=1;ans<=sum;ans++) if(pd(a,sx,0,0)) break; if(ans>sum){puts("-1");return 0;} else printf("%d\n",ans); return 0;}
1 0
- POJ2331 Water Pipe 解题报告
- POJ2331 Water pipe
- POJ2331:Water pipe(IDA*)
- poj2331 Water pipe IDA*
- IDA* POJ2331 Water pipe
- #POJ2331#Water pipe(IDA*_搜索)
- E - Pipe解题报告(来自网络)
- F - Pipe Fitters解题报告(熊禾强)
- J - Just Pour the Water 解题报告
- [LeetCode]Container With Most Water, 解题报告
- [LeetCode]Trapping Rain Water,解题报告
- Leetcode Container With Most Water 解题报告
- 【LeetCode】Container With Most Water 解题报告
- 【LeetCode】Trapping Rain Water解题报告
- LeetCode解题报告--Container With Most Water
- [LeetCode] Trapping Rain Water 解题报告
- [leetcode] 42. Trapping Rain Water 解题报告
- 【LeetCode】Container With Most Water 解题报告
- 我的见解之hibernate(四)
- 播放骨骼动画
- 2016.8.23
- 内存分析工具MAT的使用
- kafka总结
- POJ2331 Water Pipe 解题报告
- tcp初级用法:局域网聊天室-1对1-带文件传输
- 学习MVC框架的步骤
- [leetcode] 384. Shuffle an Array 解题报告
- Java基础-集合框架简要概述
- 创建AOP代理步骤
- leakcanary原理分析与AppsFly内存泄漏
- 判断固定范围内的一组数中含有7或者是7的倍数的数
- 在64位linux下编译32位程序