uva 1343 非原创
题目题意是:给你的棋盘,在A-H方向上可以拨动,问你最少拨动几次可以是中心图案的数字一致
解题思路:回溯法,剪枝
其中要把每次拨动的字母所代表的位置提前用数组表示;
然后在如果step+h()>maxd表示剪枝。
总之,用数组那里表示真的好棒,
自己太残了……!!!
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include <cstdlib> #include <stack> #include <cctype> #include <string> #include <malloc.h> #include <queue> #include <map> using namespace std; const int INF = 0xffffff; const double esp = 10e-8; const double Pi = 4 * atan(1.0); const int Maxn = 100+10; const long long mod = 2147483647; const int dr[] = {1,0,-1,0,-1,1,-1,1}; const int dc[] = {0,1,0,-1,1,-1,-1,1}; typedef long long LL; LL gac(LL a,LL b){ return b?gac(b,a%b):a; } int shift[8][7] = { {0,2,6,11,15,20,22}, {1,3,8,12,17,21,23}, {10,9,8,7,6,5,4}, {19,18,17,16,15,14,13}, {23,21,17,12,8,3,1}, {22,20,15,11,6,2,0}, {13,14,15,16,17,18,19}, {4,5,6,7,8,9,10} }; int center[] = {6,7,8,11,12,15,16,17}; int re[] = {5,4,7,6,1,0,3,2}; int d[24]; char ans[1000]; int maxd; bool is_good(){ for(int i = 1;i < 8;i++){ if(d[ center[0] ] != d[ center[i] ]) return 0; } return 1; } void _move(int x){ int tmp = d[ shift[x][0] ]; for(int i = 0;i < 6;i++) d[ shift[x][i] ] = d[shift[x][i+1] ]; d[shift[x][6]] = tmp; } int differ(int x){ int cnt = 0; for(int i = 0;i < 8;i++){ if(d[center[i]] != x){ cnt++; } } return cnt; } int h(){ return min(differ(1),min(differ(2),differ(3))); } bool dfs(int step){ if(step == maxd){ if(is_good()){ ans[step] = '\0'; return 1; } return 0; } if(step + h() > maxd) return 0; for(int i = 0;i < 8;i++){ ans[step] = i + 'A'; _move(i); if(dfs(step+1)) return 1; _move(re[i]); } return 0; } int main() { #ifndef ONLINE_JUDGE freopen("inpt.txt","r",stdin); #endif int goal[24]; char str[] = "No moves needed"; while(~scanf("%d",&goal[0]) && goal[0]){ for(int i = 1;i < 24;i++){ scanf("%d",&goal[i]); } for(maxd = 0;;maxd++){ memcpy(d,goal,sizeof(d)); if(dfs(0)) break; } printf("%s\n%d\n",(maxd?ans:str),d[center[0]]); } return 0; }