• hdu 1401 Solitaire (双向广搜)


    题意:在8 * 8 的跳棋棋盘上,给你两个状态,每个状态4个点,判断一个状态8步内能否到达另一个状态。

    分析:给定了始末状态,很典型的双向广搜。

    从始末两个方向进行广度搜索,理想情况下可以减少二分之一的搜索量,从而提高搜索速度。

    问题的关键在于状态的保存,因为四个棋子是一样的,棋盘的大小只有8*8,所以先按坐标排序之后,用二进制每三个位保存一个棋子的一个坐标,总共需要24个位。

    对双向广度搜索算法改进:

    略微修改一下控制结构,每次while循环时只扩展正反两个方向中节点数目较少的一个,可以使两边发展速度保持一定的平衡,从而减少总扩展节点个数,加快搜索速度。

    这代码写的有点挫,用俩个BFS写的,不是用同一个的,不过也省了麻烦,第一道双广,调试了一个下午。

    View Code
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<bitset>
    #define N 8
    using namespace std;
    bitset<20000010> vis1,vis2;
    int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
    bool map[N][N],flag;
    struct point
    {
    int x,y;
    };
    struct node
    {
    point p[4];
    };
    node start,end1;
    queue<node> Q1,Q2;
    bool cmp(point a,point b)
    {
    if(a.x!=b.x)
    return a.x<b.x;
    return a.y<b.y;
    }
    void get_map(point p[])
    {
    memset(map,0,sizeof(map));
    for(int i=0;i<4;i++)
    map[p[i].x][p[i].y]=1;
    }
    int get_hash(point p[])
    {
    sort(p,p+4,cmp);
    int a=0,j=7;
    for(int i=0;i<4;i++)
    {
    a|=(p[i].x<<(j*3));
    a|=(p[i].y<<(j-1)*3);
    j-=2;
    }
    return a;
    }
    void BFS1()
    {
    int a;
    int size=Q1.size();
    while(size--)
    {
    node q=Q1.front(),temp;
    Q1.pop();
    get_map(q.p);
    for(int i=0;i<4;i++)
    for(int k=0;k<4;k++)
    {
    temp=q;
    int x=q.p[i].x+dir[k][0];
    int y=q.p[i].y+dir[k][1];
    if(x<0 ||x>=N || y<0 || y>=N)
    continue;
    temp.p[i].x=x;
    temp.p[i].y=y;
    if(map[x][y])
    {
    int x1=x+dir[k][0];
    int y1=y+dir[k][1];
    if(x1<0 || x1>=N || y1<0 || y1>=N || map[x1][y1])
    continue;
    temp.p[i].x=x1;temp.p[i].y=y1;
    }
    a=get_hash(temp.p);
    if(vis1[a]) continue;
    if(vis2[a]) {
    flag=true;
    return ;
    }
    vis1[a]=true;
    Q1.push(temp);
    }
    }
    }
    void BFS2()
    {
    int a;
    int size=Q2.size();
    while(size--)
    {
    node q=Q2.front(),temp;
    Q2.pop();
    get_map(q.p);
    for(int i=0;i<4;i++)
    for(int k=0;k<4;k++)
    {
    temp=q;
    int x=temp.p[i].x+dir[k][0];
    int y=temp.p[i].y+dir[k][1];
    if(x<0 ||x>=N || y<0 || y>=N)
    continue;
    temp.p[i].x=x;
    temp.p[i].y=y;
    if(map[x][y])
    {
    int x1=x+dir[k][0];
    int y1=y+dir[k][1];
    if(x1<0 || x1>=N || y1<0 || y1>=N || map[x1][y1])
    continue;
    temp.p[i].x=x1;temp.p[i].y=y1;
    }
    a=get_hash(temp.p);
    if(vis2[a]) continue;
    if(vis1[a]) {
    flag=true; return ;
    }
    vis2[a]=true;
    Q2.push(temp);
    }
    }
    }
    int main()
    {
    while(scanf("%d %d",&start.p[0].x,&start.p[0].y)==2)
    {
    start.p[0].x--;
    start.p[0].y--;
    for(int i=1;i<4;i++)
    {
    scanf("%d %d",&start.p[i].x,&start.p[i].y);
    start.p[i].x--;start.p[i].y--;
    }
    for(int i=0;i<4;i++)
    {
    scanf("%d %d",&end1.p[i].x,&end1.p[i].y);
    end1.p[i].x--;
    end1.p[i].y--;
    }
    while(!Q1.empty())
    Q1.pop();
    while(!Q2.empty())
    Q2.pop();
    vis1.reset();
    vis2.reset();
    int a;
    a=get_hash(start.p);
    vis1[a]=true;
    int b=get_hash(end1.p);
    if(a==b) {
    printf("YES\n");
    continue;
    }
    vis2[b]=true;
    Q1.push(start);Q2.push(end1);
    int step=8;
    flag=false;
    while(step--)
    {
    if(Q1.size()<=Q2.size())
    BFS1();
    else BFS2();
    if(flag) break;
    }
    if(flag) printf("YES\n");
    else printf("NO\n");
    }
    return 0;
    }
  • 相关阅读:
    vux 使用 loading 组件
    vux 使用 font-awesome
    批处理常用符号详解
    jQuery.parseJSON vs JSON.parse
    MVC view操作(Razor语法)
    原生JavaScript技巧大收集
    .Net实现表达式计算(公式) 表达式字符串
    .Net文档下载
    MVC下载文档
    .Net实现Word文档及导出
  • 原文地址:https://www.cnblogs.com/nanke/p/2365392.html
Copyright © 2020-2023  润新知