codevs 3290 华容道

HAHAHA

BFS+SPFA.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxn 35
#define maxv 100500
#define maxe 400500
#define inf 100000007
using namespace std;
struct edge
{
    int v,w,nxt;
}e[maxe];
int n,m,qq,map[maxn][maxn],dp[maxn][maxn][4],step[maxn][maxn][4][4],tot=0,nume=0,g[maxv],v[maxn][maxn][4];
int dt[maxn][maxn],dx[]={-1,1,0,0},dy[]={0,0,-1,1},dis[maxv];
int ex,ey,sx,sy,tx,ty,s,t;
bool vis[maxv];
queue <int> q;
void addedge(int u,int v,int w)
{
    e[++nume].v=v;
    e[nume].w=w;
    e[nume].nxt=g[u];
    g[u]=nume;
}
void reset1()
{
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            for (int k=0;k<=3;k++)
                for (int l=0;l<=3;l++)
                    step[i][j][k][l]=inf;
}
void reset2()
{
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            dt[i][j]=inf;
}
void reset3()
{
    fill(dis+1,dis+tot+1,inf);
    memset(vis,false,sizeof(vis));
}
bool judge(int x,int y)
{
    if ((x>=1) && (x<=n) && (y>=1) && (y<=m) && (map[x][y]))
        return true;
    return false;
}
int bfs(int bx,int by,int tx,int ty)
{
    while (!q.empty()) q.pop();
    reset2();
    q.push(bx);q.push(by);
    dt[bx][by]=0;
    while (!q.empty())
    {
        int hx=q.front();q.pop();
        int hy=q.front();q.pop();
        if ((hx==tx) && (hy==ty)) return dt[tx][ty];
        for (int i=0;i<=3;i++)
        {
            int rx=hx+dx[i],ry=hy+dy[i];
            if ((judge(rx,ry) && (dt[rx][ry]>dt[hx][hy]+1)))
            {
                dt[rx][ry]=dt[hx][hy]+1;
                q.push(rx);q.push(ry);
            }
        }
    }
    return inf;
}
void pre_bfs()
{
    reset1();
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
        {
            if (map[i][j])
            {
                map[i][j]=0;
                for (int k=0;k<=3;k++)
                    for (int l=0;l<=3;l++)
                    {
                        int ax,ay,bx,by;
                        ax=i+dx[k];ay=j+dy[k];
                        bx=i+dx[l];by=j+dy[l];
                        if (judge(ax,ay) && judge(bx,by))
                        {
                            int r=bfs(ax,ay,bx,by);
                            if (r!=inf)
                                step[i][j][k][l]=r;
                        }
                    }
                map[i][j]=1;
            }
        }
}
void pre_build()
{
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
        {
            if (judge(i,j))
            {
                for (int k=0;k<=3;k++)
                    for (int l=0;l<=3;l++)
                    {
                        int ax,ay,bx,by;
                        ax=i+dx[k];ay=j+dy[k];
                        bx=i+dx[l];by=j+dy[l];
                        if (judge(ax,ay) && (judge(bx,by)) && (step[i][j][k][l]!=inf))
                            addedge(v[i][j][k],v[bx][by][l^1],step[i][j][k][l]+1);
                    }
            }
        }
}
void build()
{
    s=++tot;t=++tot;
    for (int i=0;i<=3;i++)
    {
        if (judge(sx+dx[i],sy+dy[i]))
        {
            map[sx][sy]=0;
            int r=bfs(ex,ey,sx+dx[i],sy+dy[i]);
            map[sx][sy]=1;
            if (r!=inf)
                addedge(s,v[sx][sy][i],r);
        }
        if (judge(tx+dx[i],ty+dy[i]))
            addedge(v[tx][ty][i],t,0);
    }
    map[sx][sy]=1;
}
int spfa()
{
    if ((sx==tx) && (sy==ty)) return 0;
    if ((sx==ex) && (sy==ey)) return -1;
    if ((map[sx][sy]==0) || (map[tx][ty]==0)) return -1;
    build();
    reset3();
    while (!q.empty()) q.pop();
    q.push(s);dis[s]=0;vis[s]=true;
    while (!q.empty())
    {
        int head=q.front();
        q.pop();
        for (int i=g[head];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if (dis[v]>dis[head]+e[i].w)
            {
                dis[v]=dis[head]+e[i].w;
                if (!vis[v])
                {
                    vis[v]=true;
                    q.push(v);
                }
            }
        }
        vis[head]=false;
    }
    if (dis[t]==inf) return -1;
    else return dis[t];
}
int main()
{
    memset(g,0,sizeof(g));
    scanf("%d%d%d",&n,&m,&qq);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
        {
            scanf("%d",&map[i][j]);
            for (int k=0;k<=3;k++)
                v[i][j][k]=++tot;
        }
    pre_bfs();
    pre_build();
    for (int i=1;i<=qq;i++)
    {
        scanf("%d%d%d%d%d%d",&ex,&ey,&sx,&sy,&tx,&ty);
        printf("%d\n",spfa());
    }
    return 0;
}
时间: 2024-11-07 23:13:09

codevs 3290 华容道的相关文章

【CodeVS 3290】【NOIP 2013】华容道

http://codevs.cn/problem/3290/ 据说2013年的noip非常难,但Purpleslz学长还是AK了.能A掉这道题真心orz. 设状态$(i,j,k)$表示目标棋子在$(i,j)$这个位置,空格在紧贴着目标棋子的$k$方向,$0≤k<4$. 因为目标棋子要移动,空格肯定在它旁边.往空格的方向走一步,空格便出现在它另一边.对于这两个状态连边,边权为1. 为了使目标棋子向某一方向移动,需要目标棋子不动,空格从紧贴着目标棋子的某一方向移动到紧贴着目标棋子的另一个方向.对于固

[ CodeVS冲杯之路 ] P2492

不充钱,你怎么AC? 题目:http://codevs.cn/problem/2492/ 在此先orz小胖子,教我怎么路径压缩链表,那么这样就可以在任意节点跳进链表啦(手动@LCF) 对于查询操作,直接树状数组(以下简称BIT)维护,修改操作就一个个暴力开方搞,再用差值单点更新BIT 不过这样会TLE,要加一点优化对不对,正如开头所说的路径压缩链表 路径压缩链表其实就是个并查集,在普通的链表里,删去两个连续的节点后会是下面这种情况,如删去2,3 当访问 2 的时候,会跳到3,但 3 已经删除了,

[CODEVS 1281] Xn数列

描述 给你6个数,m, a, c, x0, n, g Xn+1 = ( aXn + c ) mod m,求Xn http://codevs.cn/problem/1281/ 分析 比较裸的矩阵乘法题, 好久没做了, 写写思路 假设矩阵 A = { {a1, a2}, {a3, a4} }, B = { {b1, b2}, {b3, b4} }. 根据矩阵乘法的计算方法, 有 : A×B = { {a1b1+a2b2, a1b2+a2b4}, {a3b1+a4b3, a3b2+a4b4} }. 那

Codevs 1257 打砖块

1257 打砖块 http://codevs.cn/problem/1257/ 题目描述 Description 在一个凹槽中放置了n层砖块,最上面的一层有n块砖,第二层有n-1块,……最下面一层仅有一块砖.第i层的砖块从左至右编号为1,2,……i,第i层的第j块砖有一个价值a[i,j](a[i,j]<=50).下面是一个有5层砖块的例子.如果你要敲掉第i层的第j块砖的话,若i=1,你可以直接敲掉它,若i>1,则你必须先敲掉第i-1层的第j和第j+1块砖. 你的任务是从一个有n(n<=5

codevs——T1219 骑士游历

 http://codevs.cn/problem/1219/ 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 设有一个n*m的棋盘(2≤n≤50,2≤m≤50),如下图,在棋盘上有一个中国象棋马. 规定: 1)马只能走日字 2)马只能向右跳 问给定起点x1,y1和终点x2,y2,求出马从x1,y1出发到x2,y2的合法路径条数. 输入描述 Input Description 第一行2个整数n和m 第二行4个

1683 车厢重组 codevs

http://codevs.cn/problem/1683/ 时间限制: 1 s 空间限制: 1000 KB 题目等级 : 白银 Silver 题目描述 Description 在一个旧式的火车站旁边有一座桥,其桥面可以绕河中心的桥墩水平旋转.一个车站的职工发现桥的长度最多能容纳两节车厢,如果将桥旋转180度,则可以把相邻两节车厢的位置交换,用这种方法可以重新排列车厢的顺序.于是他就负责用这座桥将进站的车厢按车厢号从小到大排列.他退休后,火车站决定将这一工作自动化,其中一项重要的工作是编一个程序

codevs 1487 大批整数排序(水题日常)

时间限制: 3 s 空间限制: 16000 KB 题目等级 : 黄金 Gold 题目描述 Description !!!CodeVS开发者有话说: codevs自从换了评测机,新评测机的内存计算机制发生变化 计算内存的时候会包括栈空间 swap空间 这题的2M是单指内存空间... 十分十分抱歉 抱歉 !!! 现在有一大批(总数不超过10000000个)1到10之间的整数,现在请你从小到大进行排序输出. (测试数据将超过11MB.) 输入描述 Input Description 第一行表示将下排序

codevs 3342 绿色通道 (二分+线性DP)

codevs 3342 绿色通道 http://codevs.cn/problem/3342/ 难度等级:黄金 题目描述 Description <思远高考绿色通道>(Green Passage, GP)是唐山一中常用的练习册之一,其题量之大深受lsz等许多oiers的痛恨,其中又以数学绿色通道为最.2007年某月某日,soon-if (数学课代表),又一次宣布收这本作业,而lsz还一点也没有写…… 高二数学<绿色通道>总共有n道题目要写(其实是抄),编号1..n,抄每道题所花时间

[ CodeVS冲杯之路 ] P1368

不充钱,你怎么AC? 题目:http://codevs.cn/problem/1368/ 嗯……泡泡堂,很劲啊,其实就是个盗版的田忌赛马 http://www.cnblogs.com/hyfer/p/5853381.html 这边博客讲得很好啊,虽然不是这道题,但是方法是完全类似的 你把田忌赛马看懂了,泡泡堂就自然解出来了 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<c