题意:#字形的图形,问将中间那一块转成相同数字需要的最少步数,输出字典序最小的路径。
分析:跟hdu2234的无题I比,相对简单一点。其实也只是估价函数好理解一点,其他都差不多,还是迭代深搜+A*,也就是IDA*。
估价函数h()=8-max(在要求的八个位置中,1,2,3,的个数);
很好理解,因为没转动一步,最多只能将一个位置改为正确的。所以当前状态下,剩余的最少步数=8-max(在要求的八个位置中,1,2,3,的个数);
#include<iostream> #include<algorithm> using namespace std; int map[8][8],step; char road[100]; int hash1[8]={3,5,3,5,5,3,5,3}; void TurnCOL(int c,int flag)//转动列,c表示所在列,flag表示向上还是向下,1表示向上 { int t; if(flag) { t=map[1][c]; for(int i=2;i<=7;i++) map[i-1][c]=map[i][c]; map[7][c]=t; } else { t=map[7][c]; for(int i=6;i>=1;i--) map[i+1][c]=map[i][c]; map[1][c]=t; } } void TurnROW(int r,int flag)//转动行,r表示所在行,flag表示向右还是向左,1表示向右 { int t; if(flag) { t=map[r][7]; for(int i=6;i>=1;i--) map[r][i+1]=map[r][i]; map[r][1]=t; } else { t=map[r][1]; for(int i=2;i<=7;i++) map[r][i-1]=map[r][i]; map[r][7]=t; } } int check() { int num[4]={0}; for(int i=3;i<=5;i++) { num[map[3][i]]++; num[map[5][i]]++; } num[map[4][3]]++; num[map[4][5]]++; int t=max(num[1],max(num[2],num[3])); return t; } bool dfs(int cnt) { int t=check(); if(t==8 && cnt==step) return true; if(cnt+(8-t)>step) return false; char c; for(int i=0;i<8;i++) { c=i+'A'; road[cnt]=c; if(c=='A'|| c=='B') { TurnCOL(hash1[i],1); if(dfs(cnt+1)) return true; TurnCOL(hash1[i],0); } else if(c=='F'||c=='E') { TurnCOL(hash1[i],0); if(dfs(cnt+1))return true; TurnCOL(hash1[i],1); } else if(c=='C'||c=='D') { TurnROW(hash1[i],1); if(dfs(cnt+1)) return true; TurnROW(hash1[i],0); } else { TurnROW(hash1[i],0); if(dfs(cnt+1)) return true; TurnROW(hash1[i],1); } } return false; } int main() { int a,b; while(scanf("%d",&a)==1 && a) { scanf("%d",&b); memset(map,0,sizeof(map)); map[1][3]=a; map[1][5]=b; for(int i=2;i<=7;i++) { if(i==3|| i==5) { for(int j=1;j<=7;j++) scanf("%d",&map[i][j]); continue; } scanf("%d %d",&map[i][3],&map[i][5]); } if(check()==8) { puts("No moves needed"); printf("%d\n",map[3][3]);//忘记输出这一句,WA了一次 continue; } step=1; while(true) { if(dfs(0)) break; step++; } road[step]='\0'; puts(road); printf("%d\n",map[3][3]); } return 0; }