关闭

洛谷1979/codevs3290 华容道,74行就写完了?

标签: 搜索最短路
500人阅读 评论(0) 收藏 举报
分类:

题目分析

首先我们要明确,直接瞎广搜可以拿80分,所以怎么取舍是不是很明了?
如果你还是有一颗打正解的心…
好吧,祝你好运。
分析开始——
此题核心:状态为点,建图,进行最短路

状态为点

什么状态比较重要?目标棋子的位置,这是肯定的。再者是空格的位置。
不过事实上,重要的状态是空格和目标棋子相邻(第二步会说),也就是一个状态(x,y,tmp)是一个点,表示目标棋子在(x,y)位置,tmp代表空格的位置。我的代码中,tmp=0时表示在目标棋子上面,=1表示在下面,=2表示在左边,=3表示在右边。

建图

状态之间进行转移的代价为两点之间的边长。可以连边的节点有两种情况:
1.空格在不经过目标棋子的情况下移动到目标棋子身边另一位置。由于华容道的地图是不会改变的,所以这些边可以bfs暴力预先完成。
2.空格和目标棋子交换位置了,这两个状态之间的边长为1

进行最短路

首先bfs将空格移到目标棋子身边,然后就有四种可以作为起点的状态。因为我是使用spfa进行最短路的,所以只要合法(即空格可以移动到此位置),可以都加入处理队列。
然后spfa完毕后,有四种可能的终点(空格在目标棋子最终位置的不同方位),都查看一遍即可。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
int n,m,q,tot;
int mp[33][33],dis[33][33],qx[1010],qy[1010];
int mvx[5]={-1,1,0,0},mvy[5]={0,0,-1,1};
int h[4010],to[40010],ne[40010],w[40010];
void add(int x,int y,int z)//建边
{to[++tot]=y,ne[tot]=h[x],h[x]=tot,w[tot]=z;}
void bfs(int sx,int sy,int bx,int by,int fx){//(sx,sy):空格位置,(bx,by):目标棋子位置
    int i,ta=1,he=1,xx,yy,tx,ty;
    memset(dis,0,sizeof(dis));
    qx[1]=sx,qy[1]=sy,dis[sx][sy]=1;
    while(he<=ta){
        xx=qx[he],yy=qy[he];
        for(i=0;i<=3;++i){
            tx=xx+mvx[i],ty=yy+mvy[i];
            if(mp[tx][ty]&&!dis[tx][ty]&&(tx!=bx||ty!=by))//注意这些限制条件
                dis[tx][ty]=dis[xx][yy]+1,qx[++ta]=tx,qy[ta]=ty;
        }
        ++he;
    }
    if(fx==4)return;
    for(i=0;i<=3;++i){//情况1:空格在不经过目标棋子的情况下来到目标棋子身边其他方位
        tx=bx+mvx[i],ty=by+mvy[i];
        if((tx!=sx||ty!=sy)&&dis[tx][ty])
            add(bx*120+by*4+fx,bx*120+by*4+i,dis[tx][ty]-1);
    }
    add(bx*120+by*4+fx,sx*120+sy*4+fx^1,1);//情况2:交换空格与目标棋子的位置
}
int d[4010],inq[4010];
void spfa(int bx,int by){
    int i,x,tx,ty,tt;queue<int>q;
    for(i=0;i<=4000;++i)d[i]=1e7,inq[i]=0;
    for(i=0;i<=3;++i){//有4种可行的开始情况
        tx=bx+mvx[i],ty=by+mvy[i],tt=bx*120+by*4+i;
        if(dis[tx][ty])d[tt]=dis[tx][ty]-1,q.push(tt),inq[tt]=1;
    }
    while(!q.empty()){
        x=q.front(),q.pop(),inq[x]=0;
        for(i=h[x];i!=-1;i=ne[i])
            if(d[x]+w[i]<d[to[i]]){
            d[to[i]]=d[x]+w[i];
            if(!inq[to[i]])inq[to[i]]=1,q.push(to[i]);
        }
    }
}
int main()
{
    int i,j,sx,sy,mx,my,bx,by,ans;
    scanf("%d%d%d",&n,&m,&q);memset(h,-1,sizeof(h));
    for(i=1;i<=n;++i)
        for(j=1;j<=m;++j)scanf("%d",&mp[i][j]);
    for(i=1;i<=n;++i)
        for(j=1;j<=m;++j){
        if(!mp[i][j])continue;
        if(mp[i-1][j])bfs(i-1,j,i,j,0);
        if(mp[i+1][j])bfs(i+1,j,i,j,1);
        if(mp[i][j-1])bfs(i,j-1,i,j,2);
        if(mp[i][j+1])bfs(i,j+1,i,j,3);
    }
    while(q--){
        scanf("%d%d%d%d%d%d",&sx,&sy,&bx,&by,&mx,&my);
        if(bx==mx&&by==my){puts("0");continue;}
        bfs(sx,sy,bx,by,4);spfa(bx,by);ans=1e7;
        for(i=0;i<=3;++i)ans=min(ans,d[mx*120+my*4+i]);//有4种可行的结束情况
        if(ans<1e7)printf("%d\n",ans);
        else puts("-1");
    }
    return 0;
}
0
0
查看评论

华容道 洛谷1979 bfs+spfa

Description小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次。于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时间。 小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的: 在一个 n*m 棋盘上有 n*m 个...
  • jpwang8
  • jpwang8
  • 2017-08-05 14:30
  • 325

【NOIP2013】洛谷1979 华容道

bfs暴搜+建图+spfa
  • sdfzyhx
  • sdfzyhx
  • 2016-09-10 09:35
  • 1049

[洛谷luogu] P1979 [NOIP2013T6]华容道

60分做法:bfs四维大暴搜 O(q(nm^2))。空白块 初始位置的块:指定块 目标位置的块:目标块f[a][b][c][d] a b 表指定块 c d表空白块题解做法:我们要把指定块通过空白块移动,当且仅当空白块在指定块相邻的四个位置。 且空白块在不同四个位置,指定块移动到相邻位...
  • qq_34786702
  • qq_34786702
  • 2016-08-06 09:57
  • 331

codevs3290: [NOIP2013]华容道

题目链接 题目大意很简单,在一个不大于30×3030\times 30 的棋盘中,要求求出一个 #include #include #include #include #include using namespace std; const int N = 35, INF ...
  • qq_32365199
  • qq_32365199
  • 2016-10-11 22:01
  • 236

洛谷 1979 华容道 [NOIP2013] bfs 50分

题目: https://www.luogu.org/problem/show?pid=1979暴力50,(听说可以到70); 看不懂题解,以后再改吧,我还是太弱……唉……;#include<iostream> #include<cstdio> #include<cs...
  • qq_36312502
  • qq_36312502
  • 2017-09-24 20:32
  • 137

【最短路】【bfs】[NOIP2013] codevs3290 华容道

记得这题暴力有70...十分良心,然而它卡A*……(好像A*的估值很忧伤) 本来YY出了很诡异的姿势。。然后发现很难写……想弃疗…… 最后还是按网上流传的方法做的..不过网上的代码都好繁琐啊 = =差评…… 太久没有写代码真的生疏了不少..代码能力掉的很厉害。所以啊很多东西很久不碰也许就会忘掉了...
  • qq_21841245
  • qq_21841245
  • 2015-09-26 22:49
  • 1072

华容道01--分析

一直想写一个华容道的游戏,现在就通过学习Cocos2D3.x写一个华容道的游戏吧。 这个游戏的要求是,最后生成安卓项目,安装到自己的手机上玩玩吧! 开发周期初步定在2-3天。     华容道有多种开局方式,不同的开局方式就是不同的关卡,所以需要有一个选关界面。   再就...
  • c_boy_lu
  • c_boy_lu
  • 2015-04-14 19:39
  • 967

华容道程序制作(基础部分)

  • qing2005
  • qing2005
  • 2009-09-07 08:16
  • 4366

Java华容道

MainClass.java public class MainClass { public static void main(String args[]) { new Hua_Rong_Road(); } }Person.java import javax.swing.*;...
  • tuke_tuke
  • tuke_tuke
  • 2016-02-25 16:18
  • 1219

华容道自动求解 java版

以前自学程序设计时, 研究过华容道的自动求解,已经是几年前的事了。 当时找到一个高人写的程序,效率非常高,但是,是C语言的代码,代码可读性不好,以前弄明白过这个程序,现在又忘记了,故而这次把C语言的代码改成java版的,有重新理解一遍,并记下来,以后不怕在忘了。 C 和 javascript版的代码...
  • mu399
  • mu399
  • 2015-02-20 21:08
  • 3565
    个人资料
    • 访问:33952次
    • 积分:1602
    • 等级:
    • 排名:千里之外
    • 原创:126篇
    • 转载:3篇
    • 译文:0篇
    • 评论:27条
    litble的状态
    开学了/(ㄒoㄒ)/~~
    欢迎各路dalao来踩,企鹅号:562582061
    传送门
    最新评论