HDU 3220 IDA*搜索 || BFS

给出一个16个点所构成的图形,分别由0,1组成,每次操作可以任选其中相连的两个点(必须一个为0,一个为1),进行0,1,交换

问3步内是否可以把图形变成:0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1状态

若不行,输出more


状压存储图形状态。ida*搜索  或者 BFS都行


IDA*搜索

#include "stdio.h"
#include "string.h"

const int b[]={0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536};

const int adj[17][5]=
{
    {0,0,0,0,0},
    {0,2,3,5,9}, //1
    {0,1,4,6,10}, //2
    {0,1,4,7,11}, //3
    {0,2,3,8,12}, //4
    {0,1,6,7,13}, //5
    {0,2,5,8,14}, //6
    {0,3,5,8,15}, //7
    {0,4,6,7,16}, //8
    {0,1,10,11,13}, //9
    {0,2,9,12,14}, //10
    {0,3,9,12,15}, //11
    {0,4,10,11,16}, //12
    {0,5,9,14,15}, //13
    {0,6,10,13,16}, //14
    {0,7,11,13,16}, //15
    {0,8,12,14,15} //16
};
int ans,flag,aim;
int mark[70010];

int cal(int x)
{
    int i,cnt;
    cnt=0;
    for (i=1;i<=8;i++)
        if ((x&b[i])!=0)
        cnt++;
    return cnt;
}

void dfs(int cur,int n)
{
    int next,x,cnt,i,j;
    if (cur==aim)
    {
        flag=1;
        return ;
    }
    if (flag==1)
        return ;

    cnt=0;
    for (i=1;i<=8;i++)
        if ((cur&b[i])!=0) cnt++;
    if (n+cnt>ans)
        return ;

    for (i=1;i<=16;i++)
    {
        x=cur&b[i];
        if (x!=0)
        for (j=1;j<=4;j++)
        {
            x=cur&b[adj[i][j]];
            if (x==0)
            {
                next=cur;
                next^=b[i];
                next^=b[adj[i][j]];
                if (mark[next]==0)
                {
                    mark[next]=1;
                    dfs(next,n+1);
                    mark[next]=0;
                }
            }
        }
    }

}

int main()
{
    int t,Case,i,status,cnt,x;
    scanf("%d",&t);
    Case=1;
    memset(mark,0,sizeof(mark));
    while (t--)
    {
        status=aim=cnt=0;
        for (i=1;i<=16;i++)
        {
            scanf("%d",&x);
            if (i<=8) cnt+=x;
            status+=x*b[i];
        }
        for (i=9;i<=16;i++)
            aim+=b[i];
        printf("Case #%d: ",Case++);
        if (aim==status)
        {
            printf("0\n");
            continue;
        }
        if (cnt>3)
        {
            printf("more\n");
            continue;
        }

        ans=0;

        while(1)
        {
            ans++;
            flag=0;
            if (ans==4) break;
            mark[status]=1;
            dfs(status,0);
            mark[status]=0;
            if (flag==1)
                break;
        }

        if (ans==4)
            printf("more\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}


BFS

#include "stdio.h"
#include "string.h"
#include "queue"
using namespace std;

const int b[]={0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536};

const int adj[17][5]=
{
    {0,0,0,0,0},
    {0,2,3,5,9}, //1
    {0,1,4,6,10}, //2
    {0,1,4,7,11}, //3
    {0,2,3,8,12}, //4
    {0,1,6,7,13}, //5
    {0,2,5,8,14}, //6
    {0,3,5,8,15}, //7
    {0,4,6,7,16}, //8
    {0,1,10,11,13}, //9
    {0,2,9,12,14}, //10
    {0,3,9,12,15}, //11
    {0,4,10,11,16}, //12
    {0,5,9,14,15}, //13
    {0,6,10,13,16}, //14
    {0,7,11,13,16}, //15
    {0,8,12,14,15} //16
};
int ans,flag,aim;
int mark[70010];

int cal(int x)
{
    int i,cnt;
    cnt=0;
    for (i=1;i<=8;i++)
        if ((x&b[i])!=0) cnt++;
    return cnt;
}

int bfs(int cur)
{
    int i,j,next;
    queue<int>q;

    q.push(cur);
    memset(mark,-1,sizeof(mark));
    mark[cur]=0;

    while (!q.empty())
    {
        cur=q.front();
        q.pop();
        if (mark[cur]==3) continue;

        for (i=1;i<=16;i++)
            if ((cur&b[i])!=0)
            for (j=1;j<=4;j++)
            if ((cur&b[adj[i][j]])==0)
            {
                next=cur;
                next^=b[i];
                next^=b[adj[i][j]];
                if (mark[next]==-1 && cal(next)+mark[cur]<=3)
                {
                    mark[next]=mark[cur]+1;
                    if (next==aim) return mark[next];
                    q.push(next);
                }
            }
    }
    return -1;
}

int main()
{
    int t,Case,i,status,cnt,x;
    scanf("%d",&t);
    Case=1;

    aim=0;
    for (i=9;i<=16;i++)
        aim+=b[i];

    while (t--)
    {
        status=cnt=0;
        for (i=1;i<=16;i++)
        {
            scanf("%d",&x);
            if (i<=8) cnt+=x;
            status+=x*b[i];
        }

        printf("Case #%d: ",Case++);
        if (aim==status)
        {
            printf("0\n");
            continue;
        }
        if (cnt>3)
        {
            printf("more\n");
            continue;
        }

        ans=bfs(status);

        if (ans==-1)
            printf("more\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值