poj1077 hdu1043 Eight 八数码问题

就是八数码问题,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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值