Uvaoj10603
1.这题果断用广度搜索(BFS),最重要的是控制加进去的元素条件,条件很重要,否则很容易无限循环一直累加,知道数组超界停止...
2.深搜 最重要的是控制 递归的结束条件,还有尽可能使之不重复的列举。会控制终止条件,很关键。(否则 time limited exceed...)
3.这题用C++也很方便,set容器(内放结构体,较好用),你只用添加,set会为你判断该状态是否重复了,set就是像集合一样,只含不同的元素。
--------------------------------------------------------------------------
这个题的确很容易错!我想了两天了,为什么带了几十组数据,答案对了,却通不过,,,其实易错点就是取值total(它要求最小的情况,判断条件的设置很关键),我在这里是每一次状态就进行一次判断,判断两种情况
1.找到过 d 了,以后就避开d' < d 判断的可能,以后就直接找 满足d时的最小total就可以啦
2.在这次状态下,之前从来没有找到过d,顺便找找接近d的total最小值,我是在这里掉到坑里了。判断条件要心细!首先,先判断有没有值小于d的,找到后,在此基础上看res能不能更新,就是说res 这个记录d’的值能不能再大一些,那么就应该和该杯子中水的值进行比较。然后! 如果res和该水量一样,但可能加水过程是不一样的,还应该判断 rtotal是否能更新,去最小。
-------------------------------------------------------------------------
顺便提供一些常用测试数据,慢慢测吧...
INPUT OUTPUT
137 148 199 175 | 1213 170 |
162 66 193 183 | 426 163 |
107 55 48 62 | 0 48 |
144 29 70 157 | 0 70 |
196 46 5 131 | 0 5 |
12 132 113 171 | 0 113 |
88 178 137 74 | 88 49 |
85 58 166 110 | 7196 110 |
102 199 182 142 | 102 102 |
38 41 65 175 | 0 65 |
46 121 96 89 | 46 50 |
74 166 149 165 | 0 149 |
101 47 188 153 | 1445 153 |
151 89 179 101 | 89 90 |
1 17 67 93 | 0 67 |
151 65 74 10 | 65 9 |
8 30 64 33 | 56 32 |
170 22 71 105 | 0 71 |
108 192 142 166 | 0 142 |
22 158 158 68 | 132 66 |
25 99 6 124 | 0 6 |
54 153 188 161 | 1404 161 |
42 34 169 55 | 42 42 |
52 169 98 20 | 0 0 |
43 36 199 138 | 2279 138 |
13 189 58 70 | 0 58 |
45 120 181 176 | 375 166 |
40 43 56 116 | 0 56 |
198 42 118 38 | 126 34 |
138 29 194 106 | 1480 106 |
182 179 39 163 | 0 39 |
51 11 148 113 | 695 113 |
170 70 46 124 | 0 46 |
34 182 59 80 | 0 59 |
133 78 80 40 | 78 2 |
172 172 97 135 | 0 97 |
98 147 14 15 | 0 14 |
147 36 152 8 | 252 8 |
104 106 191 191 | 0 191 |
41 132 116 116 | 0 116 |
195 187 2 139 | 0 2 |
54 29 170 38 | 705 38 |
138 186 83 27 | 0 0 |
171 110 159 179 | 0 159 |
134 69 34 149 | 0 34 |
153 58 81 185 | 0 81 |
187 35 164 72 | 140 70 |
--------------------------------------------------------------------------
本人不太会给变量起名字,没看懂的可以问哈
#include<stdio.h>
#include<string.h>
int volume[100000][4]; //volume[][3]就是每个状态的total(倒水总量),其实用 //结构体比较简单明了,写完就后悔了
int cup[4]; //cup[3]就是d
int rtotal;
int res,ok,minto; //res 就是d’
int visit[201][201]; //很巧妙,杯子的最大量度为200,则可能状态就是0到200, //共201种,又由于水是一定的量,那么有两个就可以确定整 //个的状态,二维数组很方便又来标记
void bfs( )
{
int front,rear,i,j,dv;
front = rear =0;
minto=1000000;
int copy[4];
volume[rear][0] = 0;
volume[rear][1] = 0;
volume[rear][2] = cup[2];
volume[rear][3] = 0;
rear++;
while(front<rear)
{
copy[0]= volume[front][0];
copy[1]= volume[front][1];
copy[2]= volume[front][2];
copy[3]= volume[front][3];
if(copy[0]==cup[3] || copy[1]==cup[3] || copy[2]==cup[3])
{
if( minto > copy[3]){minto = copy[3];ok = 1;}
}
else if(ok==0)
{
for(i=0;i<3;i++)
{
if(copy[i]<cup[3] )
{
if(res < copy[i])
{
res = copy[i];
rtotal = copy[3];
}
else if(res == copy[i])
{
if(rtotal>copy[3])rtotal = copy[3];
}
}
}
}
front++;
for(i=0;i<3;i++)
{
if(copy[i]!=0)
for(j=0;j<3 ;j++)
{
if(j!=i && copy[j]<cup[j])
{
dv = cup[j]-copy[j]>copy[i]?copy[i]:cup[j]-copy[j];
volume[rear][j] = copy[j] + dv;
volume[rear][i] = copy[i] - dv;
volume[rear][3] = copy[3] + dv;
volume[rear][3-i-j] = copy[3-i-j];
if(visit[volume[rear][0]][volume[rear][1]]==0 && minto >= volume[rear][3])
{visit[volume[rear][0]][volume[rear][1]]=1;
rear++;}
}
}
}
}
}
int main()
{
int n,i;
scanf("%d",&n);
while(n--)
{
memset(visit,0,sizeof(visit));
for(i=0;i<4;i++)
{
scanf("%d",&cup[i]);
}
res = 0;ok=0;rtotal =0;
bfs();
if(ok)
printf("%d %d\n",minto,cup[3]);
else
printf("%d %d\n",rtotal,res);
}
return 0;
}