zoukankan      html  css  js  c++  java
  • NYOJ-三个水杯

    题目网址:

    http://acm.nyist.net/JudgeOnline/problem.php?pid=21

      这道题做了三天,内心是痛苦的。几次想到放弃,但是又不忍心现有的成果,又不想借鉴别人的代码。我相信我可以。就坚持下来了。最后也通过了。做这道题的感想就是流泪并快乐着。或许这也就是acmer的乐趣吧。

      这道题收获是巨大的。过后看网上说就是队列 + 搜索。我感觉则不然。我认为他是搜索 + 半个动态规划。为什么这么说呢?

      1.队列的作用在这儿就是达到递归的效果。然而我就用递归的方式实现它,这点可以忽略。概括之,就是搜索的应用。

      2.开始的时候,我只是单纯的递归去做,结果对,但是超时了(后面有超时的代码)。这里就需要用到动规的知识了。即把每一个已求得的状态到终态的距离保存下,以后会大量用到,这样就不用接着递归下去了。省了很多时间。

      具体思路是这样的:

      总共就6种情况:A->B  A->C  B->A  B->C  C->A  C->B。用递归搜索的经典形式:边界条件 + for循环。

      不断地对当前状态到终态的距离进行更新。当存在一个更小的距离时,就更新。最后的state[A][0][0]就是最后结果。需要注意的是:代码的第31行,要保证将要出现的状态没有在递归的过程中(从初态到现在这一个分支)出现过,不然就会陷入死循环。程序的146行也是个关键点:当递归返回时,上层状态到终态的距离需要下一层的加1 ,牵强的说成这是状态转移方程吧(至少有相似之处,细细品味)。is_exist数组记录的是:从初态到当前状态的这个分支中是否出现过。

    超时代码:这种情况没有进行状态保存

      1 #include <stdio.h>
      2 typedef struct {
      3     int A,B,C;
      4 }State;
      5 State remember[1000];
      6 int top;
      7 int capacity_A,capacity_B,capacity_C;
      8 int e1,e2,e3;
      9 int cnt;
     10 
     11 int judge(int a,int b,int c){
     12     for(int i = top-1; i >= 0; i--){
     13         if(a == remember[i].A && b == remember[i].B && c == remember[i].C){
     14             return 0;
     15         }
     16     }
     17     return 1;
     18 }
     19 
     20 void DFS(int a,int b,int c){
     21     if(a == e1 && b == e2 && c == e3){///递归边界
     22         if(cnt > top-1)
     23             cnt = top-1;
     24         top--;
     25         return ;
     26     }
     27 
     28     State cur;
     29 
     30     for(int i = 0; i < 6; i++){
     31         int t;/// * -> *的水量
     32         switch (i){
     33         case 0:///A->B
     34             if(a != 0 && capacity_B - b != 0){///B杯未满
     35                 if(a >= capacity_B - b){///A杯水量超过B杯剩余空间
     36                     t = capacity_B - b;
     37                 }else{
     38                     t = a;
     39                 }
     40                 if(judge(a-t, b+t, c)){
     41                     remember[top].A = a-t; remember[top].B = b+t; remember[top].C = c;
     42                     top++;
     43                     DFS(a-t, b+t, c);
     44                 }
     45 
     46             }
     47             break;
     48         case 1:///A->C
     49             if(a != 0 && capacity_C - c != 0){///C杯未满
     50                 if(a >= capacity_C - c){///A杯水量超过C杯剩余空间
     51                     t = capacity_C - c;
     52                 }else{
     53                     t = a;
     54                 }
     55                 if(judge(a - t,b,c + t)){///这种状态没有出现过
     56                     remember[top].A = a-t; remember[top].B = b; remember[top].C = c+t;
     57                     top++;
     58                     DFS(a - t,b,c + t);
     59                 }
     60             }
     61             break;
     62         case 2:///B->A
     63             if(b != 0 && capacity_A - a != 0){///a杯未满
     64                 if(b >= capacity_A - a){///B杯水量超过A杯剩余空间
     65                     t = capacity_A - a;
     66                 }else{
     67                     t = b;
     68                 }
     69                 if(judge(a+t,b-t,c)){///这种状态没有出现过
     70                     remember[top].A = a+t; remember[top].B = b-t; remember[top].C = c;
     71                     top++;
     72                     DFS(a+t,b-t,c);
     73                 }
     74             }
     75             break;
     76         case 3:///B->C
     77             if(b != 0 && capacity_C - c != 0){///c杯未满
     78                 if(b >= capacity_C - c){///B杯水量超过C杯剩余空间
     79                     t = capacity_C - c;
     80                 }else{
     81                     t = b;
     82                 }
     83                 if(judge(a, b-t, c+t)){///这种状态没有出现过
     84                     remember[top].A = a; remember[top].B = b-t; remember[top].C = c+t;
     85                     top++;
     86                     DFS(a, b-t, c+t);
     87                 }
     88             }
     89             break;
     90         case 4:///C->A
     91             if(c != 0 && capacity_A - a != 0){///a杯未满
     92                 if(c >= capacity_A - a){///C杯水量超过A杯剩余空间
     93                     t = capacity_A - a;
     94                 }else{
     95                     t = c;
     96                 }
     97                 if(judge(a+t, b, c-t)){///这种状态没有出现过
     98                     remember[top].A = a+t; remember[top].B = b; remember[top].C = c-t;
     99                     top++;
    100                     DFS(a+t, b, c-t);
    101                 }
    102             }
    103             break;
    104         case 5:///C->B
    105             if(c != 0 && capacity_B - b != 0){///b杯未满
    106                 if(c >= capacity_B - b){///C杯水量超过B杯剩余空间
    107                     t = capacity_B - b;
    108                 }else{
    109                     t = c;
    110                 }
    111                 if(judge(a, b+t, c-t)){///这种状态没有出现过
    112                     remember[top].A = a; remember[top].B = b+t; remember[top].C = c-t;
    113                     top++;
    114                     DFS(a, b+t, c-t);
    115                 }
    116             }
    117             break;
    118         }
    119     }
    120     top--;
    121 }
    122 
    123 int main(){
    124     int N;
    125     scanf("%d",&N);
    126     while(N--){
    127         scanf("%d%d%d%d%d%d",&capacity_A,&capacity_B,&capacity_C,&e1,&e2,&e3);
    128         cnt = 60000;
    129         State cur;
    130         cur.A = capacity_A; cur.B = cur.C = 0;
    131         remember[top++] = cur;
    132         DFS(capacity_A,0,0);
    133         if(cnt == 60000)
    134             printf("-1
    ");
    135         else
    136             printf("%d
    ",cnt);
    137     }
    138     return 0;
    139 }

    Accept代码:

      1 #include <stdio.h>
      2 int capacity_A,capacity_B,capacity_C;
      3 int e1,e2,e3;
      4 int cnt;
      5 int state[100][100][100];///记录状态到终态的记录,默认为INF
      6 int is_exist[100][100][100];///记录是否是递归过后的状态
      7 
      8 int DFS(int a,int b,int c){
      9     is_exist[a][b][c] = 1;
     10     if(a == e1 && b == e2 && c == e3){///递归边界
     11         state[a][b][c] = 0;
     12         return 0;
     13     }
     14 
     15     for(int i = 0; i < 6; i++){
     16         int t;/// * -> *的水量
     17         switch (i){
     18         case 0:///A->B
     19             if(a != 0 && capacity_B - b != 0){///B杯未满
     20                 if(a >= capacity_B - b){///A杯水量超过B杯剩余空间
     21                     t = capacity_B - b;
     22                 }else{
     23                     t = a;
     24                 }
     25                 if(state[a-t][b+t][c] < 60000){
     26                     if(state[a][b][c] > state[a-t][b+t][c] + 1){
     27                         state[a][b][c] = state[a-t][b+t][c] + 1;///旧状态
     28                         break;
     29                     }
     30                 }
     31                 if(is_exist[a-t][b+t][c] == 0){///60000新状态  ///没有在递归过程中出现过
     32                     int cur = DFS(a-t, b+t, c);
     33                     if(state[a][b][c] > cur+1)
     34                         state[a][b][c] = cur + 1;
     35                 }
     36 
     37             }
     38             break;
     39         case 1:///A->C
     40             if(a != 0 && capacity_C - c != 0){///C杯未满
     41                 if(a >= capacity_C - c){///A杯水量超过C杯剩余空间
     42                     t = capacity_C - c;
     43                 }else{
     44                     t = a;
     45                 }
     46                 if (state[a-t][b][c+t] < 60000){
     47                     if(state[a][b][c] > state[a-t][b][c+t] + 1){
     48                         state[a][b][c] = state[a-t][b][c+t] + 1;
     49                         break;
     50                     }
     51                 }
     52                 if(is_exist[a-t][b][c+t] == 0){///没有在递归过程中出现过
     53                     int cur = DFS(a-t,b,c+t);
     54                     if(state[a][b][c] > cur+1)
     55                         state[a][b][c] = cur + 1;
     56                 }
     57 
     58             }
     59             break;
     60         case 2:///B->A
     61             if(b != 0 && capacity_A - a != 0){///a杯未满
     62                 if(b >= capacity_A - a){///B杯水量超过A杯剩余空间
     63                     t = capacity_A - a;
     64                 }else{
     65                     t = b;
     66                 }
     67                 if(state[a+t][b-t][c] < 60000){
     68                     if(state[a][b][c] > state[a+t][b-t][c] + 1){
     69                         state[a][b][c] = state[a+t][b-t][c] + 1;
     70                         break;
     71                     }
     72                 }
     73                 if(is_exist[a+t][b-t][c] == 0){///没有在递归过程中出现过
     74                     int cur = DFS(a+t,b-t,c);
     75                     if(state[a][b][c] > cur+1)
     76                         state[a][b][c] = cur+1;
     77                 }
     78 
     79             }
     80             break;
     81         case 3:///B->C
     82             if(b != 0 && capacity_C - c != 0){///c杯未满
     83                 if(b >= capacity_C - c){///B杯水量超过C杯剩余空间
     84                     t = capacity_C - c;
     85                 }else{
     86                     t = b;
     87                 }
     88                 if(state[a][b-t][c+t] < 60000){
     89                     if(state[a][b][c] > state[a][b-t][c+t] + 1){
     90                         state[a][b][c] = state[a][b-t][c+t] + 1;
     91                         break;
     92                     }
     93                 }
     94                 if(is_exist[a][b-t][c+t] == 0){
     95                     int cur = DFS(a,b-t,c+t);
     96                     if(state[a][b][c] > cur+1)
     97                         state[a][b][c] = cur+1;
     98                 }
     99 
    100             }
    101             break;
    102         case 4:///C->A
    103             if(c != 0 && capacity_A - a != 0){///a杯未满
    104                 if(c >= capacity_A - a){///C杯水量超过A杯剩余空间
    105                     t = capacity_A - a;
    106                 }else{
    107                     t = c;
    108                 }
    109                 if(state[a+t][b][c-t] < 60000){
    110                     if(state[a][b][c] > state[a+t][b][c-t] + 1){
    111                         state[a][b][c] = state[a+t][b][c-t] + 1;
    112                         break;
    113                     }
    114                 }
    115                 if(is_exist[a+t][b][c-t] == 0){
    116                     int cur = DFS(a+t,b,c-t);
    117                     if(state[a][b][c] > cur+1)
    118                         state[a][b][c] = cur+1;
    119                 }
    120 
    121             }
    122             break;
    123         case 5:///C->B
    124             if(c != 0 && capacity_B - b != 0){///b杯未满
    125                 if(c >= capacity_B - b){///C杯水量超过B杯剩余空间
    126                     t = capacity_B - b;
    127                 }else{
    128                     t = c;
    129                 }
    130                 if(state[a][b+t][c-t] < 60000){
    131                     if(state[a][b][c] > state[a][b+t][c-t] + 1){
    132                         state[a][b][c] = state[a][b+t][c-t] + 1;
    133                         break;
    134                     }
    135                 }
    136                 if(is_exist[a][b+t][c-t] == 0){
    137                     int cur = DFS(a,b+t,c-t);
    138                     if(state[a][b][c] > cur+1)
    139                         state[a][b][c] = cur+1;
    140                 }
    141 
    142             }
    143             break;
    144         }
    145     }
    146     return state[a][b][c];
    147 }
    148 
    149 int main(){
    150     int N;
    151     scanf("%d",&N);
    152     while(N--){
    153         scanf("%d%d%d%d%d%d",&capacity_A,&capacity_B,&capacity_C,&e1,&e2,&e3);
    154         ///初始化state数组
    155         for(int i = 0; i < 100; i++)
    156             for(int j = 0; j < 100; j++)
    157                 for(int k = 0;k < 100; k++){
    158                     state[i][j][k] = 60000;
    159                     is_exist[i][j][k] = 0;
    160                 }
    161 
    162         state[capacity_A][0][0] = 61000;  is_exist[capacity_A][0][0] = 1;
    163         DFS(capacity_A,0,0);
    164         if(state[capacity_A][0][0] >= 60000)
    165             printf("-1
    ");
    166         else
    167             printf("%d
    ",state[capacity_A][0][0]);
    168     }
    169     return 0;
    170 }
  • 相关阅读:
    嵌入式系统的应用
    linux shell编程
    JS高级学习历程-1
    JavaScript入门
    二叉树 数据结构
    用css固定textarea文本域大小尺寸
    ie img 3px bug
    OpenCV-Python(1)在Python中使用OpenCV进行人脸检测
    教你用Python解决非平衡数据问题(附代码)
    图片人脸检测(OpenCV版)
  • 原文地址:https://www.cnblogs.com/yfs123456/p/5572043.html
Copyright © 2011-2022 走看看