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 1751213 170
162 66 193 183426 163
107 55 48 620 48
144 29 70 1570 70
196 46 5 1310 5
12 132 113 1710 113
88 178 137 7488 49
85 58 166 1107196 110
102 199 182 142102 102
38 41 65 1750 65
46 121 96 8946 50
74 166 149 1650 149
101 47 188 1531445 153
151 89 179 10189 90
1 17 67 930 67
151 65 74 1065 9
8 30 64 3356 32
170 22 71 1050 71
108 192 142 1660 142
22 158 158 68132 66
25 99 6 1240 6
54 153 188 1611404 161
42 34 169 5542 42
52 169 98 200 0
43 36 199 1382279 138
13 189 58 700 58
45 120 181 176375 166
40 43 56 1160 56
198 42 118 38126 34
138 29 194 1061480 106
182 179 39 1630 39
51 11 148 113695 113
170 70 46 1240 46
34 182 59 800 59
133 78 80 4078 2
172 172 97 1350 97
98 147 14 150 14
147 36 152 8252 8
104 106 191 1910 191
41 132 116 1160 116
195 187 2 1390 2
54 29 170 38705 38
138 186 83 270 0
171 110 159 1790 159
134 69 34 1490 34
153 58 81 1850 81
187 35 164 72140 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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值