http://poj.org/problem?id=2286
题目大意:如图所示有一种玩具,每次可以拉动A-H的开关使得整个行(或列)向字母方向移动一位(如果移动到头的话则到行(列)尾部)
求使得中间八个方格内数字相同的移动顺序(移动次数最小且字典序最小)和最终中间八个方格内的数的个数。
————————————————————————
说好的学完IDA*之后独立做了一道题,全程没查题解一遍AC。
对于IDA*是什么不了解的,可以看我的置顶骑士精神那道题。
首先估价函数简单点处理就是8-中间相同的数的最大个数。
然后枚举最终答案跑dfs即可,没什么太大难度(就是代码实现吗!)
#include<cstdio> #include<cstring> #include<cctype> #include<iostream> #include<map> using namespace std; int a[25]; char dir[8]={'A','B','C','D','E','F','G','H'}; int go[8][7]={{1,3,7,12,16,21,23}, {2,4,9,13,18,22,24}, {11,10,9,8,7,6,5}, {20,19,18,17,16,15,14}, {24,22,18,13,9,4,2}, {23,21,16,12,7,3,1}, {14,15,16,17,18,19,20}, {5,6,7,8,9,10,11}}; int arc[8]={5,4,7,6,1,0,3,2}; int ans; inline int h(){ int t[4]={0},res=0; for(int i=7;i<=9;i++)t[a[i]]++; for(int i=12;i<=13;i++)t[a[i]]++; for(int i=16;i<=18;i++)t[a[i]]++; for(int i=1;i<=3;i++)res=max(res,t[i]); return 8-res; } inline void turn(int k){ for(int i=1;i<7;i++){ swap(a[go[k][i]],a[go[k][i-1]]); } return; } char realdir[101]; inline bool dfs(int step){ if(step==ans){ if(!h())return 1; return 0; } if(h()+step>ans)return 0; for(int i=0;i<8;i++){ turn(i); if(dfs(step+1)){ realdir[step]=i; return 1; } return 0; } int main(){ while(scanf("%d",&a[1])!=EOF&&a[1]){ for(int i=2;i<=24;i++)scanf("%d",&a[i]); for(ans=0;;ans++){ if(dfs(0))break; } if(!ans)printf("No moves needed %d ",a[12]); else{ for(int i=0;i<ans;i++)printf("%c",dir[realdir[i]]); printf(" %d ",a[12]); } } return 0; }