Problem D
FILL
倒水问题,给你三个杯子的容量,最后一个杯子是装满水的,你需要做的就是将水从这个杯子倒入另外一个杯子,不断重复直到有一个杯子的水达到题目给你的值得容量(或者如果实际是倒不到那种要求的,就倒出最接近该目的容量的水)最后统计你在这个工程中倒的最小的水的量,和实际达到的目的容量。这两个值都要满足一定的最优值。
用杯子x给杯子y倒水时必须一直持续到把杯子y倒满或者把杯子x倒空,而不能中途停止,三个水杯当前水的容量就是一个状态,而一共有200*200个状态,用数组存储已有的状态,在遍历(深度广度都行)进行取舍,更新状态的时候同时更新目的容量的状态(即存储达到要求的总的水量和目的水容量的值),要遍历到最后的情况是因为如果最后的那个状态才是唯一达到目的容量的可能,所以不一定要用BFS,因为用BFS的原因也是因为它找到的第一个就是最优值
题目链接:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=110&page=show_problem&problem=1544
1 #include<stdio.h> 2 #include<string.h> 3 #include<malloc.h> 4 typedef struct queue{ 5 int total, from, to; //total 存储总的倒水量,当前为从from倒到to 6 int store[3]; //存储水的容量 7 struct queue *next; 8 }queue; 9 int volumn[3], d; 10 int dir[][2] = {{0, 1}, {0, 2}, {1, 0}, {1, 2}, {2, 0}, {2, 1}}; 11 int pour[202][202]; //存储遍历过的情况 12 queue Traverse() 13 {//BFs查找遍历到最后 14 int i, j, left, right, temp, cur, cnt=0; 15 queue *str, *tail, *front, *stp; 16 queue last; 17 str = tail = front = stp = NULL; 18 memset(pour, 0, sizeof(pour)); 19 memset(last.store, 0, sizeof(volumn)); 20 last.total = last.to = 0; 21 last.from = d; 22 last.next = NULL; 23 str = (queue*)malloc(sizeof(queue)); 24 str->total = str->to = 0; 25 str->from = 0; 26 str->store[0] = str->store[1] = 0, str->store[2] = volumn[2]; 27 str->next = NULL; 28 tail = str; 29 if(d == 0 || d == volumn[2]) return *str; 30 cur = d; 31 pour[0][0] = 1; 32 while(str != NULL) 33 { 34 for(i=0; i<6; ++i) 35 { 36 left = dir[i][0], right = dir[i][1]; 37 if(!(left == str->to && right == str->from)) 38 { 39 if(str->store[left] == 0 || str->store[right] == volumn[right]) 40 continue; 41 stp = (queue*)malloc(sizeof(queue)); 42 stp->total = str->total; 43 stp->from = left, stp->to = right; 44 memcpy(stp->store, str->store, sizeof(int)*3); 45 stp->next= NULL; 46 if((temp = volumn[right] - str->store[right]) >= str->store[left]) 47 { 48 stp->store[right] += str->store[left]; 49 stp->store[left] = 0; 50 stp->total += str->store[left]; 51 } 52 else 53 { 54 stp->store[left] -= temp; 55 stp->store[right] = volumn[right]; 56 stp->total += temp; 57 } 58 cur = temp = d; 59 for(j=0; j<3; ++j) 60 { 61 if((temp = d - stp->store[j]) >= 0 && temp < cur) 62 cur = temp; 63 } 64 if(cur < last.from) 65 { 66 last = *stp; 67 last.from = cur; 68 } 69 else if(cur == last.from) 70 { 71 if(last.total > stp->total) 72 last = *stp; 73 } 74 75 if(pour[stp->store[0]][stp->store[1]] == 0) 76 { 77 tail->next = stp; 78 tail = stp; 79 pour[stp->store[0]][stp->store[1]] = 1; 80 } 81 else free(stp); 82 } 83 } 84 85 stp = str; 86 str = str->next; 87 free(stp); 88 } 89 return last; 90 } 91 92 int main() 93 { 94 #ifndef ONLINE_JUDGE 95 freopen("input.txt", "r", stdin); 96 #endif 97 int T; 98 queue ans; 99 scanf("%d", &T); 100 while(T--) 101 { 102 scanf("%d%d%d%d", &volumn[0], &volumn[1], &volumn[2], &d); 103 ans = Traverse(); 104 printf("%d %d\n", ans.total, d-ans.from); 105 } 106 return 0; 107 }
#这次深刻啊,不过最后回来看也不过是耳耳,人总是很容易忘记教训的#