就是八数码问题,A*搜索的应用。
但是,杭电上的数据确实比北大的大得多,而且杭电上是多组数据的
北大:
1077 Accepted 3620K 63MS C++
杭电:
Accepted 1043312MS 252K 2719 B C++
Time Limit Exceeded10435000MS228K2338 BC++
Time Limit Exceeded10435000MS5008K3122 BC++
Wrong Answer10432625MS3928K3108 BC++
Wrong Answer10432906MS3928K3555 BC++
Runtime Error
(STACK_OVERFLOW)10430MS2252K3363 BG++
Runtime Error
(STACK_OVERFLOW)10430MS1276K3363 BC++
Runtime Error
(STACK_OVERFLOW)104
囧啊………………
不说了,代码在此:
POJ1077改了A*的模版,
HDU1043 传说中的IDA*模版,还不能完全明白透,留着以后看,各种错误。。。。
#include<iostream> #include<cstdio> #include<cstdlib> using namespace std;
#define SIZE 3
char board[SIZE][SIZE];
int my_min(int a,int b) { return a<b?a:b; }
//启发函数: 除去x之外到目标的网格距离和 const int goal_state[9][2] = {{0,0}, {0,1}, {0,2},{1,0}, {1,1}, {1,2}, {2,0}, {2,1}, {2,2}};
int h(char board[][SIZE]) { int cost = 0; for(int i=0; i<SIZE; ++i) for(int j=0; j<SIZE; ++j) { if(board[i][j] != SIZE*SIZE) { cost += abs(i - goal_state[board[i][j]-1][0]) + abs(j - goal_state[board[i][j]-1][1]); } } return cost; }
int step[4][2] = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}};//u, l, r, d char op[4] = {'u', 'l', 'r', 'd'};
char solution[1000];
int bound; //上界
bool ans; //是否找到答案
int DFS(int x, int y, int dv, char pre_move)// 返回next_bound
{
int hv = h(board);
if(hv + dv > bound)
return dv + hv;
if(hv == 0)
{
ans = true;
return dv;
}
int next_bound = 1e9;
for(int i=0; i<4; ++i)
{
if(i + pre_move == 3)//与上一步相反的移动
continue;
int nx = x + step[i][0];
int ny = y + step[i][1];
if(0<=nx && nx<SIZE && 0<=ny && ny<SIZE)
{
solution[dv] = i;
swap(board[x][y], board[nx][ny]);
int new_bound = DFS(nx, ny, dv+1, i);
if(ans)
return new_bound;
next_bound = my_min(next_bound, new_bound);
swap(board[x][y], board[nx][ny]);
}
}
return next_bound;
}
int is_ok(char a[3][3]) //这一步省了好多时间 {
int i,j,sum=0,b[10],k=0;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
if(a[i][j]!=9)
b[++k]=a[i][j];
}
}
for(i=1;i<=8;i++)
{
for(j=1;j<i;j++)
{
if(b[i]<b[j])sum++;
}
}
if(sum%2==0)return 1;
else return 0;
}
void IDA_star(int sx, int sy) { bound = h(board);//初始代价 while(!ans && bound <= 100)//上限 bound = DFS(sx, sy, 0, -10); }
int main() { int sx, sy;//起始位置 char c; int i,j; i=0;j=0; while(cin>>c) { if(c=='x') { sx = i; sy = j; board[i][j]=9; //k记录x所在的位置 } else board[i][j]=c-'0'; if(i!=2||j!=2) { if(j==2) { i++,j=0; } else j++; } else { i=0;j=0; ans=false; if(is_ok(board)) IDA_star(sx, sy); if(ans) { for(int i=0; i<bound; ++i) cout<<op[solution[i]]; cout<<"/n"; } else cout<<"unsolvable/n"; } } return 0; }
#include<cstdio> #include<cstdlib> #include<cstring> #include<queue> #include<algorithm> using namespace std; //A*算法 //f(n)=g(n)+h(n) //f(n) 是从初始点经由节点n到目标点的估价函数, //g(n) 是在状态空间中从初始节点到n节点的实际代价, //h(n) 是从n到目标节点最佳路径的估计代价。 int hash[362885]; int pre[362885]; int b[9]={1,1,2,6,24,120,720,5040,40320};//用n!标记数列,用来分配地址 struct node { int p;//x所在的位置 int f;//f=g+h int g;//已用的代价 int h;//到目标的代价 int num[9]; node(int pp,int ff,int gg,int hh,int *a) { p=pp; f=ff; g=gg; h=hh; for(int i=0;i<9;i++) num[i]=a[i]; } bool operator<(const node x)const { return g+h>x.g+x.h;//比较f()=g()+h() } }; int fun(int *a)//与顺序冲突的次数 { int i,j,s=0; for(i=0;i<9;i++) for(j=i+1;j<9;j++) if(a[j]&&a[i]>a[j]) s++; return s; } int cal(int *num)//计算到目标的代价,即h { int i,s=0; for(i=0;i<9;i++) s+=abs((num[i]+8)%9%3-i%3)+abs((num[i]+8)%9/3-i/3);//未懂 return s; } int Hash(int *num)//用n!来分配地址 { int i,j,k,h=0; for(i=0;i<9;i++) { for(k=0,j=i+1;j<9;j++) if(num[i]>num[j]) k++; h+=k*b[num[i]]; } return h; } int A_star(node st) { priority_queue<node> q; int p,h,f; int num[9]; q.push(st); while(!q.empty()) { node x=q.top(); q.pop(); memcpy(num,x.num,sizeof(num)); p=x.p; f=Hash(num); if(cal(num)==0)//到目标的代价为0,即已经找到目标 return f; if(p%3!=0)//不是最左列 { swap(num[p],num[p-1]);//l操作 if(!hash[h=Hash(num)]) { hash[h]=1; pre[h]=f; q.push(node(p-1,f,x.g+1,cal(num),num)); } swap(num[p],num[p-1]); } if(p%3!=2)//不是最右列 { swap(num[p],num[p+1]);//r操作 if(!hash[h=Hash(num)]) { hash[h]=2; pre[h]=f; q.push(node(p+1,f,x.g+1,cal(num),num)); } swap(num[p],num[p+1]); } if(p/3!=0)//不是第一行 { swap(num[p],num[p-3]);//u操作 if(!hash[h=Hash(num)]) { hash[h]=3; pre[h]=f; q.push(node(p-3,f,x.g+1,cal(num),num)); } swap(num[p],num[p-3]); } if(p/3!=2)//不是最后一行 { swap(num[p],num[p+3]);//d操作 if(!hash[h=Hash(num)]) { hash[h]=4; pre[h]=f; q.push(node(p+3,f,x.g+1,cal(num),num)); } swap(num[p],num[p+3]); } } return -1; } void dfs(int x) { char d[6]="0lrud";//方向 if(pre[pre[x]]!=-1) dfs(pre[x]); printf("%c",d[hash[x]]); } int main() { int num[9],i,j,k; char c; for(i=0;i<9;i++) { while((c=getchar())==' '); if(c=='x') num[k=i]=0; //k记录x所在的位置 else num[i]=c-'0'; } if((fun(num)&1))//冲突次数为奇数,无法通过交换来使其解决 puts("unsolvable"); else { hash[j=Hash(num)]=1; pre[j]=-1; i=A_star(node(k,0,0,cal(num),num)); if(i!=-1) dfs(i); else puts("unsolvable"); } return 0; }
听说用单纯的DFS也能过……被秒杀了T T