就是八数码问题,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