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;
}
时间: 2024-08-03 22:13:14

HDU 3220 IDA*搜索 || BFS的相关文章

HDU 1560 IDA*搜索

用N个串中找到最短的公共串(不要求连续,只要相对位置一样即可) 迭代加深搜索即可 剪枝:当前的深度+最少还有加深的深度是否大于限制的长度,若是,则退回. #include "stdio.h" #include "string.h" const char ch[10]="ATCG"; int deep,n; char s[10][10]; int pos[10]; int Max(int a,int b) { if (a<b) return

hdu 4771 Stealing Harry Potter&#39;s Precious (2013亚洲区杭州现场赛)(搜索 bfs + dfs) 带权值的路径

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4771 题目意思:'@'  表示的是起点,'#' 表示的是障碍物不能通过,'.'  表示的是路能通过的: 目的:让你从 '@' 点出发,然后每个点只能走一次,求出最小的距离: 解题思路:先用 bfs 求解出任意两点之间的距离,用 ans[i][j],表示点 i 到点  j 的距离: 然后用 dfs 递归求出从起点经过所有点的距离中,比较出最小的: AC代码: 1 #include<iostream>

HDU 1428 漫步校园 (BFS+优先队列+记忆化搜索)

题目地址:HDU 1428 先用BFS+优先队列求出所有点到机房的最短距离,然后用记忆化搜索去搜. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #incl

HDU 1242 &amp;&amp; ZOJ 1649( BFS (队列 || 优先队列)).

~~~~ 突然发现一篇搜索的题目都有写.昨天发现道bfs题目,HDU上AC, ZOJ上WA.不得不说HDU上的数据之水.. 今天早起刷题有了思路,并用队列和单调队列都写了一遍,0MS飘过~~ ~~~~ 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1242 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=649 ~~~~ 首先有坑的地方是friends,对嘛,朋友有很多,ang

HDU 4801 Pocket Cube BFS

链接:http://vjudge.net/contest/view.action?cid=51289#problem/K 题意:给一个小魔方(每面只有四个小块),每个小块有自己的颜色(一共六种颜色,每种颜色四块),问经过最多N次操作(N<=7),每次操作是将魔方某一面转动90度,最多能使多少个面的四个小块颜色都相同. 思路:每次操作产生6种状态,(向前,向后,向左,向右,向上,向下,左半魔方向前和右半魔方向后的操作产生的状态本质是一样的)直接BFS搜索,可能产生的状态一共有6^7种,中间比较麻烦

HDU 1242 -Rescue (双向BFS)&amp;&amp;( BFS+优先队列)

题目链接:Rescue 进度落下的太多了,哎╮(╯▽╰)╭,渣渣我总是埋怨进度比别人慢...为什么不试着改变一下捏.... 开始以为是水题,想敲一下练手的,后来发现并不是一个简单的搜索题,BFS做肯定出事...后来发现题目里面也有坑 题意是从r到a的最短距离,"."相当时间单位1,"x"相当时间单位2,求最短时间 HDU 搜索课件上说,这题和HDU1010相似,刚开始并没有觉得像剪枝,就改用  双向BFS   0ms  一Y,爽! 网上查了一下,神牛们竟然用BFS+

HDU 1495 非常可乐 (BFS)

 问题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1495 题目大意:一个瓶子容积s,两个杯子容积分别n,m,并且都没有刻度(不能比对噢!).相互倒水,求平分的他们的最少倒水次数. 思路:暴力搜索吧.并且求最少,(即最优解),所以上BFS: 思考:状态,转移过程,怎么剪纸. 惨痛的debug,我不解释了. 源代码: #include<iostream> #include<cstdio> #include<queue> #

[BZOJ 1085][SCOI 2005]骑士精神(IDA*搜索)

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1085 考虑到深度不超过15,IDA*搜索可做. 估价函数h()=当前不在目标位置的棋子个数. 然后其他细节就和普通的迭代加深一样了. #include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm>

hdu 1429 状压bfs

#include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <map> #define inf 0x3f3f3f3f #define ll __in