hdoj 1043 八数码已编码 Time Limit Exceeded

#include
#include
#include
#include
using namespace std;
typedef int state[9];

const int maxstate=1000000;
state st[maxstate],goal={1,2,3,4,5,6,7,8,0};
int dist[maxstate];
char record[maxstate]; //前一个状态到这一个的移动
int father[maxstate];//记录夫节点配合record【】
int vis[362880];
int fact[9];
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};
const char dir[4]={'u','d','l','r'};
void init_lookup_table()
{
fact[0]=1;
for(int i=1;i fact[i]=fact[i-1]*i;
}
int try_to_insert(int s) //编码
{
int code=0;
for(int i=0;i {
int cnt=0;
for(int j=i+1;j if(st[s][j] cnt++;
code+=fact[8-i]*cnt;
}
if(vis[code]) return 0;
return vis[code]=1;
}
int bfs()
{
init_lookup_table();
int front=1,rear=2;
while(front {
state& s=st[front];
if(memcmp(goal,s,sizeof(s))==0) return front;
int z;
for(z=0;z if(!s[z])
break;
int x=z/3,y=z%3;
for(int d=0;d {
int newx=x+dx[d];
int newy=y+dy[d];
int newz=newx*3+newy;
if(newx>=0&&newx=0&&newy {
state& t=st[rear];
memcpy(&t,&s,sizeof(s));
t[newz]=s[z];
t[z]=s[newz];
dist[rear]=dist[front]+1;
if(try_to_insert(rear)) //如果这个状态未被访问
{
father[rear]=front;
record[rear]=dir[d];
rear++;
}
}
}
front++;
}
return 0;
}
int main(void)
{
char ch[100];
int index;
while(gets(ch)!=NULL) //输入
{
index=0;
memset(vis,0,sizeof(vis));
memset(dist,0,sizeof(dist));
for(int i=0;i {
if(ch[i]>='0'&&ch[i]<='9')
st[1][index++]=ch[i]-'0';
else if(ch[i]=='x')
st[1][index++]=0;
}
int ans=bfs();
if(ans>0)
{
string str;
int v=ans;
int k=dist[ans];
while(k--)
{
str.push_back(record[v]); //路径生成
v=father[v];
}
for(int i=str.length()-1;i>=0;i--)
printf("%c",str[i]);
printf("\n");
}
else
printf("unsolvable\n");
}
return 0;
}

https://blog.csdn.net/qq_38987374/article/details/79110603

#include
#include
#include
#include
using namespace std;
typedef int state[9];
const int maxstate=1000000;
state st[maxstate],goal={1,2,3,4,5,6,7,8,0};
int dist[maxstate];
char record[maxstate]; //前一个状态到这一个的移动
int father[maxstate];//记录夫节点配合record【】
int vis[362880];
int fact[9];
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};
const char dir[4]={'u','d','l','r'};
void init_lookup_table()
{
fact[0]=1;
for(int i=1;i fact[i]=fact[i-1]*i;
}
int try_to_insert(int s) //编码
{
int code=0;
for(int i=0;i {
int cnt=0;
for(int j=i+1;j if(st[s][j] cnt++;
code+=fact[8-i]*cnt;
}
if(vis[code]) return 0;
return vis[code]=1;
}
int bfs()
{
init_lookup_table();
int front=1,rear=2;
while(front {
state& s=st[front];
if(memcmp(goal,s,sizeof(s))==0) return front;
int z;
for(z=0;z if(!s[z])
break;
int x=z/3,y=z%3;
for(int d=0;d {
int newx=x+dx[d];
int newy=y+dy[d];
int newz=newx*3+newy;
if(newx>=0&&newx=0&&newy {
state& t=st[rear];
memcpy(&t,&s,sizeof(s));
t[newz]=s[z];
t[z]=s[newz];
dist[rear]=dist[front]+1;
if(try_to_insert(rear)) //如果这个状态未被访问
{
father[rear]=front;
record[rear]=dir[d];
rear++;
}
}
}
front++;
}
return 0;
}
int main(void)
{
char ch[100];
int index;
while(gets(ch)!=NULL) //输入
{
index=0;
memset(vis,0,sizeof(vis));
memset(dist,0,sizeof(dist));
for(int i=0;i {
if(ch[i]>='0'&&ch[i]<='9')
st[1][index++]=ch[i]-'0';
else if(ch[i]=='x')
st[1][index++]=0;
}
int ans=bfs();
if(ans>0)
{
string str;
int v=ans;
int k=dist[ans];
while(k--)
{
str.push_back(record[v]); //路径生成
v=father[v];
}
for(int i=str.length()-1;i>=0;i--)
printf("%c",str[i]);
printf("\n");
}
else
printf("unsolvable\n");
}
return 0;
}
再发一遍上边有地方没了

四个头文件为
cstdio
iostream
cstring
cstring

上面有缺再发一次,我的问题时理论这个程序已经不会走重复的状态节点了
网上我看到了一个跟我的思路相近的 我试了他的200ms过le
我这个用了5000ms直接爆了。
求教原因

 #include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
typedef int state[9];
const int maxstate=1000000;
state st[maxstate],goal={1,2,3,4,5,6,7,8,0};
int dist[maxstate];
char record[maxstate];  //前一个状态到这一个的移动
int father[maxstate];//记录夫节点配合record【】
int vis[362880];
int fact[9];
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};
const char dir[4]={'u','d','l','r'};
void init_lookup_table()
{
    fact[0]=1;
    for(int i=1;i<9;i++)
        fact[i]=fact[i-1]*i;
}
int try_to_insert(int s)   //编码
{
    int code=0;
    for(int i=0;i<9;i++)
    {
        int cnt=0;
        for(int j=i+1;j<9;j++)
            if(st[s][j]<st[s][i])
                cnt++;
        code+=fact[8-i]*cnt;
    }
    if(vis[code]) return 0;
    return vis[code]=1;
}
int bfs()
{
    init_lookup_table();
    int front=1,rear=2;
    while(front<rear)
    {
        state& s=st[front];
        if(memcmp(goal,s,sizeof(s))==0) return front;
        int z;
        for(z=0;z<9;z++)
            if(!s[z])
                break;
        int x=z/3,y=z%3;
        for(int d=0;d<4;d++)
        {
            int newx=x+dx[d];
            int newy=y+dy[d];
            int newz=newx*3+newy;
            if(newx>=0&&newx<3&&newy>=0&&newy<3)
            {
                state& t=st[rear];
                memcpy(&t,&s,sizeof(s));
                t[newz]=s[z];
                t[z]=s[newz];
                dist[rear]=dist[front]+1;
                if(try_to_insert(rear))   //如果这个状态未被访问
                {
                    father[rear]=front;
                    record[rear]=dir[d];
                    rear++;
                }
            }
        }
        front++;
    }
    return 0;
}
int main(void)
{
    char ch[100];
    int index;
    while(gets(ch)!=NULL)    //输入
    {
        index=0;
        memset(vis,0,sizeof(vis));
        memset(dist,0,sizeof(dist));
        for(int i=0;i<100;i++)
        {
            if(ch[i]>='0'&&ch[i]<='9')
                st[1][index++]=ch[i]-'0';
            else if(ch[i]=='x')
                st[1][index++]=0;
        }
        int ans=bfs();
        if(ans>0)
        {
            string str;
            int v=ans;
            int k=dist[ans];
            while(k--)
            {
                str.push_back(record[v]);  //路径生成
                v=father[v];
            }
            for(int i=str.length()-1;i>=0;i--)
                printf("%c",str[i]);
            printf("\n");
        }
        else
            printf("unsolvable\n");
    }
    return 0;
}

不好意思,原因我大概知道了
我的代码每输入一次就重新进一次bfs 每次都从初始状态走到goal
再测试样例多的时候可能超时,所以hdoj后台这一题可能存在大量样例
而反向bfs打表,bfs一次后只用查表就可以了