历届试题 九宫重排
时间限制:1.0s 内存限制:256.0MB
问题描述
如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。


我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
我们把第一个图的局面记为:12345678.
把第二个图的局面记为:123.46758
显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
输入格式
输入第一行包含九宫的初态,第二行包含九宫的终态。
输出格式
输出最少的步数,如果不存在方案,则输出-1。
样例输入
12345678.
123.46758
123.46758
样例输出
3
样例输入
13524678.
46758123.
46758123.
样例输出
22
fuck啊,只对了80%;骚年努力!没有过不去的坎,没有A不掉的题!
#define _CRT_SECURE_NO_DEPRECATE //A*八数码问题 #include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<vector> #include<cmath> #define MAX 1 using namespace std; int dx[4] = { 0, 0, 1, -1 }, dy[4] = { 1, -1, 0, 0 }; class NODE{ public: NODE(){ memset(m, 0, sizeof(m)); flag = f = g = h = 0; par = NULL; } ~NODE(){} char m[3][3]; //矩阵对应的十进制数 int flag; //估价函数 int f, g, h; //空格坐标 int tx, ty; //父节点 NODE *par; //转换函数 void m2f(){ flag=0; for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ if(m[i][j]!='.')flag = 10*flag+(m[i][j]-'0'); else { flag *= 10; tx = i; ty = j; } } } } void init(char *c){ int i=0; for(int j=0;j<3;j++)for(int k=0;k<3;k++)m[j][k]=c[i++]; m2f(); } //计算f void calf(NODE T){ //h是与目标位置不同数的个数 for (int i = 0; i < 3; i++)for (int j = 0; j < 3; j++)if (m[i][j] != T.m[i][j])h++; //h:离对应点的距离 for (int i = 0; i < 3; i++)for (int j = 0; j < 3; j++){ for (int k = 0; k < 3; k++)for (int l = 0; l < 3; l++) if (m[i][j] == T.m[k][l]){ h += abs(k + l - i - j); } } if (par != NULL){ g = par->g + 1; f = g + h; } else f = h; } void print(){ printf("%d ",flag); } }; NODE orig,targ; //Open表中按f从小到大排序 struct great{ bool operator()(NODE N1,NODE N2){ return N1.f > N2.f; } }; //Open表和Close表 priority_queue<NODE,vector<NODE>, great> OList; vector<NODE> CList; vector<NODE>::iterator itor; //A* void AStar(){ int step = 0; char temp; //找到结果 bool find = false; OList.push(orig); //如果Open表空,无解 while (!OList.empty()){ //把Open表第一个取出,记为n,加入Close表 NODE n = OList.top(); OList.pop(); CList.push_back(n); //n是否为目标节点,是则成功退出 if (n.h == 0){ find = true; step = n.g; break; } //n是否可扩展 for (int i = 0; i < 4; i++){ int x = n.tx + dx[i], y = n.ty + dy[i]; if (x>-1 && x<3 && y>-1 && y < 3){ NODE t; for (int i = 0; i < 3; i++)for (int j = 0; j < 3; j++)t.m[i][j] = n.m[i][j]; t.tx = x; t.ty = y; temp = t.m[n.tx][n.ty]; t.m[n.tx][n.ty] = t.m[x][y]; t.m[x][y] = temp; t.m2f(); t.par = &n; t.calf(targ); if (n.par == NULL || t.flag != n.par->flag){ bool inCL = false; for (itor = CList.begin(); itor != CList.end(); itor++){ if (t.flag == itor->flag){ inCL = true; break; } } if (!inCL)OList.push(t); } } } } if (find){ printf("%d ", step); } else{ printf("-1 "); } } int main() { char c[10]; //while(1){ gets(c); orig.init(c); gets(c); targ.init(c); orig.calf(targ); AStar(); //} return 0; }
用set来设Close表,结果可以在1s内出来,但是结果是错的,还是80%对了只。
#define _CRT_SECURE_NO_DEPRECATE //A*八数码问题 #include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<set> #include<vector> #include<cmath> #include<algorithm> #define MAX 1 using namespace std; int dx[4] = { 0, 0, 1, -1 }, dy[4] = { 1, -1, 0, 0 }; class NODE{ public: NODE(){ memset(m, 0, sizeof(m)); flag = f = g = h = 0; par = NULL; } ~NODE(){} char m[3][3]; //矩阵对应的十进制数 int flag; //估价函数 int f, g, h; //空格坐标 int tx, ty; //父节点 NODE *par; //转换函数 void m2f(){ flag=0; for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ if(m[i][j]!='.')flag = 10*flag+(m[i][j]-'0'); else { flag *= 10; tx = i; ty = j; } } } } void init(char *c){ int i=0; for(int j=0;j<3;j++)for(int k=0;k<3;k++)m[j][k]=c[i++]; m2f(); } //计算f void calf(NODE T){ //h是与目标位置不同数的个数 for (int i = 0; i < 3; i++)for (int j = 0; j < 3; j++)if (m[i][j] != T.m[i][j])h++; //h:离对应点的距离 for (int i = 0; i < 3; i++)for (int j = 0; j < 3; j++){ for (int k = 0; k < 3; k++)for (int l = 0; l < 3; l++) if (m[i][j] == T.m[k][l]){ h += abs(k + l - i - j); } } if (par != NULL){ g = par->g + 1; f = g + h; } else f = h; } void print(){ printf("%d ",flag); } }; NODE orig,targ; //Open表中按f从小到大排序 struct great{ bool operator()(NODE N1,NODE N2){ return N1.f > N2.f; } }; //Open表和Close表 priority_queue<NODE, vector<NODE>, great> OList; //vector<NODE> CList; //vector<NODE>::iterator itor; set<int> cList; set<int>::iterator iter; bool ccmp(NODE n1,NODE n2){ //便于二分查找 return n1.flag<n2.flag; } //A* void AStar(){ int step = 0; char temp; //找到结果 bool find = false; OList.push(orig); //如果Open表空,无解 while (!OList.empty()){ //把Open表第一个取出,记为n,加入Close表 NODE n = OList.top(); OList.pop(); //CList.push_back(n); //CList[++clen]=n; cList.insert(n.flag); //n是否为目标节点,是则成功退出 if (n.h == 0){ find = true; step = n.g; break; } //n是否可扩展 for (int i = 0; i < 4; i++){ int x = n.tx + dx[i], y = n.ty + dy[i]; if (x>-1 && x<3 && y>-1 && y < 3){ NODE t; for (int i = 0; i < 3; i++)for (int j = 0; j < 3; j++)t.m[i][j] = n.m[i][j]; t.tx = x; t.ty = y; temp = t.m[n.tx][n.ty]; t.m[n.tx][n.ty] = t.m[x][y]; t.m[x][y] = temp; t.m2f(); t.par = &n; t.calf(targ); if (n.par == NULL || t.flag != n.par->flag){ bool inCL = false; // for (itor = CList.begin(); itor != CList.end(); itor++){ // if (t.flag == itor->flag){ inCL = true; break; } // } /* c1=0;c2=clen; sort(CList,CList+clen+1,ccmp); while(c1<c2){ mid=(c1+c2)/2; if(CList[mid].flag>t.flag)c2=mid-1; else if(CList[mid].flag<t.flag)c1=mid+1; else if(CList[mid].flag==t.flag){inCL=true;break;} } */ iter=cList.find(t.flag); if(iter!=cList.end())inCL=true; if (!inCL)OList.push(t); } } } } if (find){ printf("%d ", step); } else{ printf("-1 "); } //printf("%d ",CList.size()); } //逆序对是否同偶或同奇 bool comp(int x, int y); int main() { char c[10]; //while(1){ gets(c); orig.init(c); gets(c); targ.init(c); orig.calf(targ); if(comp(orig.flag, targ.flag)) AStar(); else printf("-1 "); //} return 0; } inline bool comp(int x, int y){ int t1[8],t2[8], i1=0,i2=0, m = 100000000, h; while(x){ h=x/m; if(h>0)t1[i1++]=h; x%=m; m/=10; } m = 100000000; while(y){ h=y/m; if(h>0)t2[i2++]=h; y%=m; m/=10; } /*for(int i=0;i<8;i++)printf("%4d",t1[i]); printf(" "); for(int i=0;i<8;i++)printf("%4d",t2[i]); printf(" ");*/ m=0;h=0; for(int i=0;i<8;i++)for(int j=i+1;j<8;j++){ if(t1[i]>t1[j])m++; if(t2[i]>t2[j])h++; } //printf("%d %d ",m,h); if(h%2==m%2)return true; else return false; }