POJ2331 Water pipe

来源:互联网 发布:网站美工的基本原则 编辑:程序博客网 时间:2024/05/18 03:24

      题目的大意是,有起点(x1,y1),终点(x2,y2),要铺设从起点到终点的水管,水管的长度分别为L1,L2,L3,L4,水管的数量为C1,C2,C3,C4(管子的种类最多是4),找出铺设水管所需最小的水管总数。

    看到这题首先是DFS,首先计算x方向上所需最小的管子数,然后计算y方向上所需最小的管子数,二者相加便可得最小的水管总数。可是纠结了好几天,编程能力还是太差,只想到了两种剪枝,一种是每种水管在x轴或y轴上只能沿着一个方向,二是判断剩余的水管能不能到达终点,这两种剪枝太弱了,直接是TLE。后来在网上受一个做法的提示:利用每种水管在x轴或y轴上只能沿着一个方向的特点进行枚举。例如,水管L1,在x轴上数目的可能性为-C1,-(C1-1),-(C1-2)···(C1-1),C1,然后进行枚举计算,找到符合要求的最小的数目。那么4种水管最多的可能性是21^4,相对于DFS而言,这已经是非常小的了。

    代码如下:

#include <stdio.h>#define  abs(x) ((x)>0?(x):-(x))#define  max_num 0xffffint cnt;int l[4],c[4],buffer[4];void search(int start,int end,int k);int main(){int x1,y1,x2,y2,k;int i,j,result;//freopen("test.txt","r",stdin);    while(scanf("%d %d %d %d %d",&x1,&y1,&x2,&y2,&k)!=EOF){cnt=max_num;result=0;for(i=0;i<k;i++)c[i]=buffer[i]=0;for(i=0;i<k;i++)scanf("%d",&l[i]);for(i=0;i<k;i++)scanf("%d",&c[i]);search(x1,x2,k);if(cnt!=max_num){result=cnt;cnt=max_num;for(i=0;i<k;i++)c[i]=buffer[i];search(y1,y2,k);}if(cnt!=max_num)   printf("%d\n",cnt+result);elseprintf("-1\n");}return 0;}void search(int start,int end,int k){int c1,c2,c3,c4;int temp,num;for(c1=-1*c[0];c1<=c[0];c1++)for(c2=-1*c[1];c2<=c[1];c2++)for(c3=-1*c[2];c3<=c[2];c3++)for(c4=-1*c[3];c4<=c[3];c4++){temp=c1*l[0]+c2*l[1]+c3*l[2]+c4*l[3];if(abs(temp)==abs(end-start)){num=abs(c1)+abs(c2)+abs(c3)+abs(c4);if(num<cnt){buffer[0]=c[0]-abs(c1);buffer[1]=c[1]-abs(c2);buffer[2]=c[2]-abs(c3);buffer[3]=c[3]-abs(c4);cnt=num;}}}}


0 0