题意简述:平分液体问题。输入s、n和m三个数,分别代表可乐和2个杯子,三个容器可以互相倒,问能不能把s中的可乐平分,能的话输出最小倒杯子的次数,不能就输出NO。
问题分析:开始的时候,所有可乐在s中,2个杯子n和m都空着。过程中,可以将任何1个容器中的可乐倒到另外某个容器中,或将目标容器倒满,或将源容器倒空。因为容器没有刻度,只能这样。这个过程中,如果出现某个容器空,另外2个容器可乐相同则成功。如果开始的时候,可乐的容量是奇数,则不可能平分可乐。容器间可乐倒来倒去,每次有6种倒法,对这6种倒法进行试探即可。求的是最少倒的次数,所以可以用BFS实现。
程序说明:搜索过的状态就不需要再搜索了,用数组notvist[][][]来标记搜索过的状态。
AC的C++语言程序如下:
/* HDU1495 非常可乐 */ #include <iostream> #include <queue> #include <cstring> #include <cstdio> using namespace std; const int MAXN = 100; int s, n, m, s2; bool notvist[MAXN+1][MAXN+1][MAXN+1]; struct node { int s, n, m, level; }; int bfs() { if(s % 2 == 1) return -1; queue<node> q; s2 = s / 2; memset(notvist, true, sizeof(notvist)); node f; f.s = s; f.n = 0; f.m = 0; f.level=0; q.push(f); notvist[f.s][f.n][f.m] = false; while(!q.empty()) { f = q.front(); q.pop(); if((f.s == f.n && f.s == s2) || (f.s == f.m && f.s == s2) || (f.m == f.n && f.m == s2)) return f.level; node v; // s --> n if(f.s && n - f.n > 0) { if(f.s > n - f.n) { // s > n的剩余容量 v.s = f.s - (n - f.n); v.n = n; v.m = f.m; } else { // s <= n的剩余容量 v.s = 0; v.n = f.n + f.s; v.m = f.m; } if(notvist[v.s][v.n][v.m]) { notvist[v.s][v.n][v.m] = false; v.level = f.level + 1; q.push(v); } } // s --> m if(f.s && m - f.m > 0) { if(f.s > m - f.m) { // s > m的剩余容量 v.s = f.s - (m - f.m); v.n = f.n; v.m = m; } else { // s <= m的剩余容量 v.s = 0; v.n = f.n; v.m = f.m + f.s; } if(notvist[v.s][v.n][v.m]) { notvist[v.s][v.n][v.m] = false; v.level = f.level + 1; q.push(v); } } // n --> s if(f.n && s - f.s > 0) { if(f.n > s - f.s) { // n > s的剩余容量 v.s = s; v.n = f.n - (s - f.s); v.m = f.m; } else { // n <= s的剩余容量 v.s = f.s + f.n; v.n = 0; v.m = f.m; } if(notvist[v.s][v.n][v.m]) { notvist[v.s][v.n][v.m] = false; v.level = f.level + 1; q.push(v); } } // n --> m if(f.n && m - f.m > 0) { if(f.n > m - f.m) { // n > m的剩余容量 v.s = f.s; v.n = f.n - (m - f.m); v.m = m; } else { // n <= m的剩余容量 v.s = f.s; v.n = 0; v.m = f.m + f.n; } if(notvist[v.s][v.n][v.m]) { notvist[v.s][v.n][v.m] = false; v.level = f.level + 1; q.push(v); } } // m --> s if(f.m && s - f.s > 0) { if(f.m > s - f.s) { // m > s的剩余容量 v.s = s; v.n = f.n; v.m = f.m - (s - f.s); } else { // m <= s的剩余容量 v.s = f.s + f.m; v.n = f.n; v.m = 0; } if(notvist[v.s][v.n][v.m]) { notvist[v.s][v.n][v.m] = false; v.level = f.level + 1; q.push(v); } } // m --> n if(f.m && n - f.n > 0) { if(f.m > n - f.n) { // m > n的剩余容量 v.s = f.s; v.n = n; v.m = f.m - (n - f.n); } else { // m <= n的剩余容量 v.s = f.s; v.n = f.n + f.m; v.m = 0; } if(notvist[v.s][v.n][v.m]) { notvist[v.s][v.n][v.m] = false; v.level = f.level + 1; q.push(v); } } } return -1; } int main() { while(scanf("%d%d%d", &s, &n, &m) != EOF) { if(s == 0 && n == 0 && m == 0) break; int ans = bfs(); if(ans < 0) printf("NO "); else printf("%d ", ans); } return 0; }
参考链接:非常可乐。