长安大学新生赛 H题 拉面女神的魔盒
再简单说明一下题意,规定一开始按钮状态为0 0 0 0 0 0,输入终点状态,求最少的操作步数,对于每个按钮,有以下规定:
按钮①:可以任意想顺时针或者逆时针旋转,一次转动一格
按钮②:当6个旋钮的数字中奇数偶数个数为相同时才能转动,向顺时针或者逆时针转动一格
按钮③:只能向逆时针方向转动,一次转动7格。
按钮④:只能向逆时针方向转动,一次转动(sum % 9 + 1)格,sum为当前六个数之和
按钮⑤:当①③⑤这三个旋钮数字之和正好为9的时候才能转动,顺时针或者逆时针旋转一格
按钮⑥:当按钮②的数字为0的时候才能转动,只能向顺时针转动,一次转动三格。
这个题一开始反应的是能否直接用DFS并判重来做。。然而明显不可以。
后来发现其实这肯定是个BFS的题目,进而根据题目知道终点,知道起点这个特性,想到可以用A*或者双向BFS来做,但是不知道怎么列启发式函数,所以就用双向BFS来做吧。代码很长,因为正向和反向不完全一样的判断条件,比较坑。。。未提交过,可能有错误,欢迎指正。
代码如下:
#include <iostream> #include <cstring> #include <cstdio> #include <map> #include <vector> #include <cmath> #include <iomanip> #include <algorithm> #include <queue> using namespace std; struct VIS{ int flag; int step; }vis[1000001]; int dis[2] = {1, -1}; struct num{ int n[6]; int step; friend bool operator <(num a, num b) { return a.step < b.step; } }; int ans[6]; int init[6]; bool judge(num a){ for(int i = 0; i < 6; i ++) if(a.n[i] != ans[i]); return false; return true; } int total(num a){ int i, sum; sum = 0; for(i = 0; i < 6; i ++) sum = sum * 10 + a.n[i]; return sum; } int bfs(void){ memset(vis, 0, sizeof(vis)); queue<num> q; queue<num> p; num pre, lst; int i, t, sp = 0; long sum; for(i = 0; i < 6; i ++) pre.n[i] = init[i]; sum = total(pre); vis[sum].flag = 1; vis[sum].step = 0; pre.step = 0; q.push(pre); for(i = 0; i < 6; i ++) lst.n[i] = ans[i]; sum = total(lst); vis[sum].flag = 2; vis[sum].step = 0; lst.step = 0; p.push(lst); while(!q.empty() && !p.empty()){ while(q.front().step == sp){ pre = q.front(); q.pop(); for(i = 0; i < 6; i ++){ if(i == 0){ for(t = 0; t < 2; t ++){ lst = pre; lst.n[0] = pre.n[0] + dis[t]; if(lst.n[i] < 0) lst.n[i] += 10; else if(lst.n[i] >= 10) lst.n[i] -= 10; sum = total(lst); lst.step = pre.step + 1; if(vis[sum].flag == 1) continue; if(vis[sum].flag == 2) return lst.step + vis[sum].step; vis[sum].flag = 1; vis[sum].step = lst.step; q.push(lst); } } else if(i == 1){ int temp = 0; for(int j = 0; j < 6; j ++){ if(pre.n[j] % 2) temp ++; else temp --; } if(temp != 0) continue; for(t = 0; t < 2; t ++){ lst = pre; lst.n[1] = pre.n[1] + dis[t]; if(lst.n[i] < 0) lst.n[i] += 10; else if(lst.n[i] >= 10) lst.n[i] -= 10; sum = total(lst); lst.step = pre.step + 1; if(vis[sum].flag == 1) continue; if(vis[sum].flag == 2) return lst.step + vis[sum].step; vis[sum].flag = 1; vis[sum].step = lst.step; q.push(lst); } } else if(i == 2){ lst = pre; lst.n[2] = pre.n[2] + 7; if(lst.n[i] < 0) lst.n[i] += 10; else if(lst.n[i] >= 10) lst.n[i] -= 10; sum = total(lst); lst. step = pre.step + 1; if(vis[sum].flag == 1) continue; if(vis[sum].flag == 2) return lst.step + vis[sum].step; vis[sum].flag = 1; vis[sum].step = lst.step; q.push(lst); } else if(i == 3){ lst = pre; int temp = 0; for(int j = 0; j < 6; j ++){ temp += lst.n[j]; } temp = temp % 9 + 1; lst.n[3] = pre.n[3] + temp; if(lst.n[i] < 0) lst.n[i] += 10; else if(lst.n[i] >= 10) lst.n[i] -= 10; sum = total(lst); lst. step = pre.step + 1; if(vis[sum].flag == 1) continue; if(vis[sum].flag == 2) return lst.step + vis[sum].step; vis[sum].flag = 1; vis[sum].step = lst.step; q.push(lst); } else if(i == 4 && (pre.n[0] + pre.n[2] + pre.n[4] == 9)){ for(t = 0; t < 2; t ++){ lst = pre; lst.n[4] = pre.n[4] + dis[t]; if(lst.n[i] < 0) lst.n[i] += 10; else if(lst.n[i] >= 10) lst.n[i] -= 10; sum = total(lst); lst.step = pre.step + 1; if(vis[sum].flag == 1) continue; if(vis[sum].flag == 2) return lst.step + vis[sum].step; vis[sum].flag = 1; vis[sum].step = lst.step; q.push(lst); } } else if(i == 5 && pre.n[1] == 0){ lst = pre; lst.n[5] = pre.n[5] - 3; if(lst.n[i] < 0) lst.n[i] += 10; else if(lst.n[i] >= 10) lst.n[i] -= 10; sum = total(lst); lst. step = pre.step + 1; if(vis[sum].flag == 1) continue; if(vis[sum].flag == 2) return lst.step + vis[sum].step; vis[sum].flag = 1; vis[sum].step = lst.step; q.push(lst); } } } while(p.front().step == sp){ pre = p.front(); p.pop(); for(i = 0; i < 6; i ++){ if(i == 0){ for(t = 0; t < 2; t ++){ lst = pre; lst.n[0] = pre.n[0] + dis[t]; if(lst.n[i] < 0) lst.n[i] += 10; else if(lst.n[i] >= 10) lst.n[i] -= 10; sum = total(lst); lst.step = pre.step + 1; if(vis[sum].flag == 2) continue; if(vis[sum].flag == 1) return lst.step + vis[sum].step; vis[sum].flag = 2; vis[sum].step = lst.step; p.push(lst); } } else if(i == 1){ for(t = 0; t < 2; t ++){ lst = pre; lst.n[1] = pre.n[1] + dis[t]; if(lst.n[i] < 0) lst.n[i] += 10; else if(lst.n[i] >= 10) lst.n[i] -= 10; int temp = 0; for(int j = 0; j < 6; j ++) if(lst.n[j] % 2) temp ++; else temp --; if(temp != 0) continue; sum = total(lst); lst.step = pre.step + 1; if(vis[sum].flag == 2) continue; if(vis[sum].flag == 1) return lst.step + vis[sum].step; vis[sum].flag = 2; vis[sum].step = lst.step; p.push(lst); } } else if(i == 2){ lst = pre; lst.n[2] = pre.n[2] - 7; if(lst.n[i] < 0) lst.n[i] += 10; else if(lst.n[i] >= 10) lst.n[i] -= 10; sum = total(lst); lst. step = pre.step + 1; if(vis[sum].flag == 2) continue; if(vis[sum].flag == 1) return lst.step + vis[sum].step; vis[sum].flag = 2; vis[sum].step = lst.step; p.push(lst); } else if(i == 3){ for(t = 0; t < 10; t ++){ lst.n[3] = pre.n[3] - t; if(lst.n[i] < 0) lst.n[i] += 10; else if(lst.n[i] >= 10) lst.n[i] -= 10; int temp = 0; for(int j = 0; j < 6; j ++){ temp += lst.n[j]; } if(temp % 9 + 1 != i) continue; sum = total(lst); lst.step = pre.step + 1; if(vis[sum].flag == 2) continue; if(vis[sum].flag == 1) return lst.step + vis[sum].step; vis[sum].flag = 2; vis[sum].step = lst.step; p.push(lst); } } else if(i == 4){ for(t = 0; t < 2; t ++){ lst = pre; lst.n[4] = pre.n[4] + dis[t]; if(lst.n[i] < 0) lst.n[i] += 10; else if(lst.n[i] >= 10) lst.n[i] -= 10; if(lst.n[0] + lst.n[2] + lst.n[4] != 9) continue; sum = total(lst); lst.step = pre.step + 1; if(vis[sum].flag == 2) continue; if(vis[sum].flag == 1) return lst.step + vis[sum].step; vis[sum].flag = 2; vis[sum].step = lst.step; p.push(lst); } } else if(i == 5 && pre.n[1] == 0){ lst = pre; lst.n[5] = pre.n[5] + 3; if(lst.n[i] < 0) lst.n[i] += 10; else if(lst.n[i] >= 10) lst.n[i] -= 10; sum = total(lst); lst.step = pre.step + 1; if(vis[sum].flag == 2) continue; if(vis[sum].flag == 1) return lst.step + vis[sum].step; vis[sum].flag = 2; vis[sum].step = lst.step; p.push(lst); } } } ++ sp; } return -1; } int T; int main(void){ char c; //freopen("out.txt", "r", stdin); //freopen("in.txt", "w",stdout); cin >> T; while(T --){ bool flag = false; for(int i = 0; i < 6; i ++){ cin >> ans[i]; init[i] = 0; if(ans[i]) flag = true; } if(!flag) cout << "0" << endl; int res = bfs(); cout << res << endl; } return 0; }