Uvaoj10603(BFS + 判断条件是重点)

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;
}

 

你可能感兴趣的:(有向图,BFS广搜)