loj2613 「NOIP2013」华容道[最短路]

感觉和以前做过的一个推箱子很像,都是可以用bfs解决的,而且都是手玩出结论。

因为起始棋子肯定是要和空格交换的,所以第一件事是先把空格移到棋子旁边。然后讨论怎么设计搜索状态。由于和推箱子实在太像了,所以直接借鉴,发现空格总是要贴着棋子走的要不然就是换个贴的方向继续走(这里的走就是指交换)。于是绑定两者,设计状态$f_{i,j,dir}$表示在棋子在某个格子,空格在上下左右四方位时候的最小移动次数。显然可以暴力bfs跑,但是这样没有经过优化,效率不高,实际上只要把它改的像最短路算法一点就行了,比如套个dijkstra,把每种状态和他可以推到的下一步状态(分为交换,或者空格跑到另一侧,这个的步数可以提前预处理)之间连边,边权即步数,这样建个图之后就是最短路了,起点有4个,终点有4个,$O(Qn^2\text{log}n^2)$,避免了bfs庞大的搜索树。

然后注意一个很容易忽略的细节。。我第一发就是这么挂掉的。。起点和终点在同一个位置要特判,不然会加上空格到起点的距离然后跪好多点。

code可能是我有史以来写过的最丑的,一堆循环展开。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<queue>
 7 #define dbg(x) cerr << #x << " = " << x <<endl
 8 using namespace std;
 9 typedef long long ll;
10 typedef double db;
11 typedef pair<int,int> pii;
12 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
13 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
14 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
15 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
16 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
17 template<typename T>inline T read(T&x){
18     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
19     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
20 }
21 const int N=30+2,INF=0x3f3f3f3f;
22 int mp[N][N],f[N][N][4][4],id[N][N][4],cnt;
23 int n,m,Q,hx,hy,sx,sy,tx,ty;
24 int qx[114514],qy[114514],dis[N][N],l,r;
25 inline void bfs_step(int x,int y){
26     memset(dis,0x3f,sizeof dis);qx[l=r=1]=x,qy[1]=y,dis[x][y]=0;
27     while(l<=r){
28         int i=qx[l],j=qy[l++];
29         if(!mp[i-1][j]&&MIN(dis[i-1][j],dis[i][j]+1))qx[++r]=i-1,qy[r]=j;
30         if(!mp[i+1][j]&&MIN(dis[i+1][j],dis[i][j]+1))qx[++r]=i+1,qy[r]=j;
31         if(!mp[i][j-1]&&MIN(dis[i][j-1],dis[i][j]+1))qx[++r]=i,qy[r]=j-1;
32         if(!mp[i][j+1]&&MIN(dis[i][j+1],dis[i][j]+1))qx[++r]=i,qy[r]=j+1;
33     }
34 }
35 struct thxorz{int to,nxt,w;}G[100000];
36 int Head[5000],tot;
37 inline void Addedge(int x,int y,int z){
38     G[++tot].to=y,G[tot].nxt=Head[x],Head[x]=tot,G[tot].w=z;
39     G[++tot].to=x,G[tot].nxt=Head[y],Head[y]=tot,G[tot].w=z;
40 }
41 int dist[5000];
42 priority_queue<pii,vector<pii>,greater<pii> > q;
43 #define y G[j].to
44 inline void dij(int xx,int yy){
45     memset(dist,0x3f,sizeof dist);
46     if(id[xx][yy][0])q.push(make_pair(dist[id[xx][yy][0]]=dis[xx-1][yy],id[xx][yy][0]));
47     if(id[xx][yy][1])q.push(make_pair(dist[id[xx][yy][1]]=dis[xx][yy+1],id[xx][yy][1]));
48     if(id[xx][yy][2])q.push(make_pair(dist[id[xx][yy][2]]=dis[xx+1][yy],id[xx][yy][2]));
49     if(id[xx][yy][3])q.push(make_pair(dist[id[xx][yy][3]]=dis[xx][yy-1],id[xx][yy][3]));
50     while(!q.empty()){
51         int x=q.top().second,d=q.top().first;q.pop();
52         if(dist[x]^d)continue;
53         for(register int j=Head[x];j;j=G[j].nxt)if(MIN(dist[y],d+G[j].w))q.push(make_pair(dist[y],y));
54     }
55 }
56 #undef y
57 int main(){//freopen("test.in","r",stdin);freopen("test.ans","w",stdout);
58     read(n),read(m),read(Q);memset(mp,0x3f,sizeof mp);
59     for(register int i=1;i<=n;++i)for(register int j=1;j<=m;++j)read(mp[i][j]),mp[i][j]^=1;
60     for(register int i=1;i<=n;++i)for(register int j=1;j<=m;++j)if(!mp[i][j]){
61         mp[i][j]=1;
62         if(!mp[i-1][j])bfs_step(i-1,j),f[i][j][0][1]=dis[i][j+1],f[i][j][0][2]=dis[i+1][j],f[i][j][0][3]=dis[i][j-1],id[i][j][0]=++cnt;
63         if(!mp[i][j+1])bfs_step(i,j+1),f[i][j][1][0]=dis[i-1][j],f[i][j][1][2]=dis[i+1][j],f[i][j][1][3]=dis[i][j-1],id[i][j][1]=++cnt;
64         if(!mp[i+1][j])bfs_step(i+1,j),f[i][j][2][0]=dis[i-1][j],f[i][j][2][1]=dis[i][j+1],f[i][j][2][3]=dis[i][j-1],id[i][j][2]=++cnt;
65         if(!mp[i][j-1])bfs_step(i,j-1),f[i][j][3][0]=dis[i-1][j],f[i][j][3][1]=dis[i][j+1],f[i][j][3][2]=dis[i+1][j],id[i][j][3]=++cnt;
66         mp[i][j]=0;
67     }
68     for(register int i=1;i<=n;++i)for(register int j=1;j<=m;++j)if(!mp[i][j]){
69         for(register int thx=0;thx<4;++thx)for(register int orz=0;orz<4;++orz)
70             if(orz^thx&&id[i][j][thx]&&id[i][j][orz])Addedge(id[i][j][thx],id[i][j][orz],f[i][j][thx][orz]);
71         if(id[i][j][0])Addedge(id[i][j][0],id[i-1][j][2],1);
72         if(id[i][j][3])Addedge(id[i][j][3],id[i][j-1][1],1);
73     }
74     while(Q--){
75         read(hx),read(hy),read(sx),read(sy),read(tx),read(ty);
76         if(sx==tx&&sy==ty){puts("0");continue;}
77         mp[sx][sy]=1;bfs_step(hx,hy);mp[sx][sy]=0;
78         dij(sx,sy);
79         int tmp=_min(dist[id[tx][ty][0]],_min(dist[id[tx][ty][1]],_min(dist[id[tx][ty][2]],dist[id[tx][ty][3]])));
80         printf("%d\n",tmp<INF?tmp:-1);
81     }
82     return 0;
83 }
View Code

总结:棋盘类问题求最小解有常用方法就是最短路建模,注意考虑状态设计有效性,必要时跑分层图。

转载于:https://www.cnblogs.com/saigyouji-yuyuko/p/11594873.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
4S店客户管理小程序-毕业设计,基于微信小程序+SSM+MySql开发,源码+数据库+论文答辩+毕业论文+视频演示 社会的发展和科学技术的进步,互联网技术越来越受欢迎。手机也逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。手机具有便利性,速度快,效率高,成本低等优点。 因此,构建符合自己要求的操作系统是非常有意义的。 本文从管理员、用户的功能要求出发,4S店客户管理系统中的功能模块主要是实现管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理,用户客户端:首页、车展、新闻头条、我的。门店客户端:首页、车展、新闻头条、我的经过认真细致的研究,精心准备和规划,最后测试成功,系统可以正常使用。分析功能调整与4S店客户管理系统实现的实际需求相结合,讨论了微信开发者技术与后台结合java语言和MySQL数据库开发4S店客户管理系统的使用。 关键字:4S店客户管理系统小程序 微信开发者 Java技术 MySQL数据库 软件的功能: 1、开发实现4S店客户管理系统的整个系统程序; 2、管理员服务端;首页、个人中心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理等。 3、用户客户端:首页、车展、新闻头条、我的 4、门店客户端:首页、车展、新闻头条、我的等相应操作; 5、基础数据管理:实现系统基本信息的添加、修改及删除等操作,并且根据需求进行交流信息的查看及回复相应操作。
现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本微信小程序医院挂号预约系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此微信小程序医院挂号预约系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。微信小程序医院挂号预约系统有管理员,用户两个角色。管理员功能有个人中心,用户管理,医生信息管理,医院信息管理,科室信息管理,预约信息管理,预约取消管理,留言板,系统管理。微信小程序用户可以注册登录,查看医院信息,查看医生信息,查看公告资讯,在科室信息里面进行预约,也可以取消预约。微信小程序医院挂号预约系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值