题目链接:http://codeup.cn/problem.php?cid=100000609&pid=4
吐槽
实在是太口怕了,一个上午才做2道题,debug使我疯狂
注意点
- 考虑使用map来映射
- abc三个桶的状态构成一个整数,表示这种状态,要求这个数是能独一无二代表某种状态
最初使用tmpNum = st.a * 100 + st.b * 10 + st.c;
问题就出在这种表示方法上,题目给出的每个桶的容积abc,对于这三个数,每个数最少1位,最多3位,若是采用上面的方法,只是进⑩,很有可能出现两种不同的状态,使得两个状态得到同一个整数
比如对于起始状态100 0 0
某一个中间状态为50 20 30
,得到的整数是5230
,但是5230
对应的状态总共有4种!tmpNum a b c 5230 48 42 10 5230 49 31 20 5230 50 20 30 5230 51 9 40
- 采用新的表示方法:每个数占3位,最多9位,还在int范围内(<abs(2*109))
tmpNum = st.a * 1000000 + st.b * 1000 + st.c;
代码
#include <iostream>
#include <queue>
#include <unordered_map>
#include <cstring>
using namespace std;
struct Node {
int a, b, c, step;
};
int ca, cb, cc, k;
// 1 a->b 2 b->a
// 3 a->c 4 c->a
// 5 b->c 6 c->b
bool judge(Node top,int way) {
int a = top.a;
int b = top.b;
int c = top.c;
if ((way == 1) && (a <= 0 || b >= cb))
return false;
if ((way == 2) && (b <= 0 || a >= ca))
return false;
if ((way == 3) && (a <= 0 || c >= cc))
return false;
if ((way == 4) && (c <= 0 || a >= ca))
return false;
if ((way == 5) && (b <= 0 || c >= cc))
return false;
if ((way == 6) && (c <= 0 || b >= cb))
return false;
return true;
}
void f(int& a, int& b,const int xb) {
if (a + b > xb) {
a = a + b - xb;
b = xb;
} else {
b = a + b;
a = 0;
}
}
// 1 a->b 2 b->a
// 3 a->c 4 c->a
// 5 b->c 6 c->b
Node dosomething(Node top, int way) {
int a = top.a;
int b = top.b;
int c = top.c;
if (way == 1) f(a, b,cb);
if (way == 2) f(b,a,ca);
if (way == 3) f(a, c,cc);
if (way == 4) f(c,a,ca);
if (way == 5) f(b,c,cc);
if (way == 6) f(c,b,cb);
Node node;
node.a = a;
node.b = b;
node.c = c;
node.step = top.step + 1;
return node;
}
queue<Node> q;
unordered_map<int,bool> mp;
//const int maxn = 150;
//int a[maxn][maxn][maxn] = { 0 };
int BFS(Node st) {
mp.clear();
//memset(a, 0, sizeof(a));
while (!q.empty()) {
q.pop();
}
q.push(st);
int tmpNum = st.a * 1000000 + st.b * 1000 + st.c;
mp[tmpNum] = true;
//a[st.a][st.b][st.c] = 1;
while (!q.empty()) {
Node top = q.front();
q.pop();
if (top.a == k || top.b == k || top.c == k)
return top.step;
// 6种操作
for (int way = 1; way <= 6; way++) {
if (judge(top, way)) {
Node newNode = dosomething(top, way);
int tmpNum2 = newNode.a * 1000000 + newNode.b * 1000 + newNode.c;
if (mp[tmpNum2] == false)
//if (a[newNode.a][newNode.b][newNode.c] == 0)
{
q.push(newNode);
mp[tmpNum2] = true;
//a[newNode.a][newNode.b][newNode.c] = 1;
}
}
}
}
return -1;
}
int main() {
while (scanf("%d%d%d%d",&ca,&cb,&cc,&k)!=EOF) {
Node st = { ca,0,0,0 };
int step = BFS(st);
if (step != -1) {
printf("yes\n%d\n", step);
} else {
printf("no\n");
}
}
return 0;
}