poj 1077 + HOJ 10466 + hdu 1043 eight

此题我用了2种方法去做,bfs和双向 bfs 现在还在学A*,准备学会了再用A*去试试,单向bfs只过了poj,双向bfs全部都过了,具体思想就是搜索加判重,有用hash,有用康托展开,不过康托展开比较方便,因为毕竟可以一一对应,就不用判重的时候还要比较9个数了,康托展开的计算方法是:从最高位开始,在它位数前面比它小的所有数的数量再乘以它(位数-1)的阶乘,再把每一位的这个值给加起来,就是要求的。讲起来很晦涩,其实就是代表数字排列顺序的先后,比如321的康托展开 = 2×2!+ 1×1!=5是第5位,因为是从0开始数的,所以就是3!-1就是5了,312=2×2!=4 还有123 = 0,这样就可以让0-8总共9个数一一和9!一一对应起来了。

HOJ10466代码:这只用求步数就可以了不用给出路径,但是数据挺强大的,我双向BFS还用了828ms。

#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
using namespace std;
#define MAX 500000
#define NMAX 1000007
int cantor[9],vis[MAX],dist[MAX];
int ans;
bool found;
short dx[4]= {-1,0,1,0},dy[4]= {0,1,0,-1};
typedef struct status
{
    int state[9];
}status;
queue<status>q1;
queue<status>q2;
status st,go;
void initcantor()
{
    cantor[0] = 1;
    for(int i = 1; i < 9; i++)
        cantor[i] = cantor[i-1]*i;

}

void init()
{
    ans=0;
    memset(dist,0,sizeof(dist));
    memset(vis,0,sizeof(vis));
    while(!q1.empty()) q1.pop();
    while(!q2.empty()) q2.pop();
}

int gethash(status &s)
{
    int code = 0;
    for(int i = 0; i < 9; i++)
    {
        int cnt = 0;
        for(int j = i+1; j < 9; j++)
            if(s.state[i] > s.state[j]) cnt++;
        code += cantor[8-i]*cnt;
    }
    return code;
}

void bfs_expend(queue<status>&q,int flag)
{
    int ff;
    if(flag == 1)
        ff = 2;
    else
        ff = 1;
    status temp = q.front();
    q.pop();
    int z;
    for(z = 0; temp.state[z] != 0; z++);
    int x = z/3,y = z%3;
    int h = gethash(temp);
    for(int i = 0; i < 4; i++)
    {
        status t1=temp;
        int newx = x+dx[i],newy = y+dy[i];
        if(newx>=0 && newx < 3 && newy>=0 && newy < 3)
        {
            int newz = 3*newx+newy;
            int k = t1.state[newz];
            t1.state[z] = k;
            t1.state[newz] = 0;
            int newh = gethash(t1);
            if(vis[newh] == ff)
            {
                ans = dist[newh] + dist[h]+1;
                found = true;
                return;
            }
            if(vis[newh] != flag)
            {
                q.push(t1);
                vis[newh] = flag;
                dist[newh] = dist[h] + 1;
            }
        }
    }
}

void TBFS()
{
    found = false;
    memset(vis,0,sizeof(vis));
    vis[gethash(st)] = 1;
    vis[gethash(go)] = 2;
    q1.push(st);
    q2.push(go);
    while(!q1.empty() || !q2.empty())
    {
        if(!q1.empty())
            bfs_expend(q1,1);
        if(found)
            return;
        if(!q2.empty())
            bfs_expend(q2,2);
        if(found)
            return;
    }
}

int main()
{
    initcantor();
    init();
    int i,j;
    for(i = 0; i < 9; i++) scanf("%d",&st.state[i]);
    for(i = 0; i < 9; i++) scanf("%d",&go.state[i]);
    if(memcmp(st.state,go.state,sizeof(st.state)) == 0)
    {
        printf("0\n");
        return 0;
    }
    TBFS();
    if(!ans)
        printf("-1\n");
    else
        printf("%d\n",ans);
    return 0;
}


poj和hdu的代码

#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
using namespace std;
#define MAX 365000
int cantor[9],vis[MAX];
int move1[MAX],move2[MAX];
int father1[MAX],father2[MAX];
int path[1000],record;
bool found;
short dx[4]= {-1,0,1,0},dy[4]= {0,1,0,-1};
char pos1[5] = "urdl";
char pos2[5] = "dlur";
typedef struct status
{
    int state[9];
} status;
queue<status>q1;
queue<status>q2;
stack<char>ss;
status st,go;
void initcantor()
{
    cantor[0] = 1;
    for(int i = 1; i < 9; i++)
        cantor[i] = cantor[i-1]*i;

}

void init()
{
    record=0;
    found = false;
    memset(vis,0,sizeof(vis));
    while(!q1.empty()) q1.pop();
    while(!q2.empty()) q2.pop();
}

int gethash(status &s)
{
    int code = 0;
    for(int i = 0; i < 9; i++)
    {
        int cnt = 0;
        for(int j = i+1; j < 9; j++)
            if(s.state[i] > s.state[j]) cnt++;
        code += cantor[8-i]*cnt;
    }
    return code;
}

void bfs_expend(queue<status>&q,int flag)
{
    int ff;
    if(flag == 1)
        ff = 2;
    else
        ff = 1;
    status temp = q.front();
    q.pop();
    int z;
    for(z = 0; temp.state[z] != 0; z++);
    int x = z/3,y = z%3;
    int h = gethash(temp);
    for(int i = 0; i < 4; i++)
    {
        status t1=temp;
        int newx = x+dx[i],newy = y+dy[i];
        if(newx>=0 && newx < 3 && newy>=0 && newy < 3)
        {
            int newz = 3*newx+newy;
            int k = t1.state[newz];
            t1.state[z] = k;
            t1.state[newz] = 0;
            int newh = gethash(t1);
            if(vis[newh] == ff)
            {
                record = newh;
                if(ff == 2)
                {
                    move1[newh] = i;
                    father1[newh] = h;
                }
                else
                {
                    move2[newh] = i;
                    father2[newh] = h;
                }
                found = true;
                return;
            }
            if(vis[newh] != flag)
            {
                if(flag == 1)
                {
                    move1[newh] = i;
                    father1[newh] = h;
                }
                else
                {
                    move2[newh] = i;
                    father2[newh] = h;
                }
                q.push(t1);
                vis[newh] = flag;
            }
        }
    }
}

void TBFS()
{
    vis[gethash(st)] = 1;
    vis[gethash(go)] = 2;
    q1.push(st);
    q2.push(go);
    while(!q1.empty() || !q2.empty())
    {
        if(!q1.empty())
            bfs_expend(q1,1);
        if(found)
            return;
        if(!q2.empty())
            bfs_expend(q2,2);
        if(found)
            return;
    }
}

void find_path(int start,int end)
{
    int temp = record;
    ss.push(pos1[ move1[temp] ]);
    while(father1[temp] != start)
    {
        temp = father1[temp];
        ss.push(pos1[ move1[temp] ]);
    }
    while(!ss.empty())
    {
        printf("%c",ss.top());
        ss.pop();
    }
    temp = record;
    printf("%c",pos2[ move2[temp] ]);
    while(father2[temp] != end)
    {
        temp = father2[temp];
        printf("%c",pos2[ move2[temp] ]);
    }
    printf("\n");
}


int main()
{
    initcantor();
    int i,j;
    for(i = 0; i < 8; i++) go.state[i] = i+1;
    go.state[8] = 0;
    int coo=0;
    char temp;
    while(cin>>temp)
    {
        init();
        if(temp == 'x') st.state[0] = 0;
        else st.state[0] = temp-'0';
        for(i = 1; i < 9; i++)
        {
            cin>>temp;
            if(temp == 'x') st.state[i] = 0;
            else st.state[i] = temp-'0';
        }
        coo=0;
        for(i = 1; i < 9; i++)
            for(j = 0; j < i; j++)
            {
                if(!st.state[i] || !st.state[j]) continue;
                if(st.state[i] < st.state[j])
                    coo++;
            }
        if(coo%2 == 1) printf("unsolvable\n");
        else
        {
            TBFS();
            find_path(gethash(st),gethash(go));
        }
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值