题目的大意是,有起点(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 0xffff
int 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);
else
printf("-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;
}
}
}
}