Japan 2005 Domestic Cleaning Robot /// BFS 状压 二进制位运算 结构体内构造函数 oj22912
题目大意:
输入w h,接下来输入h行w列的图
' . ':干净的点; ' * ' :垃圾; ' x ' : 墙; ' o ' : 初始位置;
输出 清理掉所有垃圾的最短路径长度 无则输出-1
7 5
.......
.o...*.
.......
.*...*.
.......
15 13
.......x.......
...o...x....*..
.......x.......
.......x.......
.......x.......
...............
xxxxx.....xxxxx
...............
.......x.......
.......x.......
.......x.......
..*....x....*..
.......x.......
10 10
..........
..o.......
..........
..........
..........
.....xxxxx
.....x....
.....x.*..
.....x....
.....x....
0 0
8
49
-1
题解
用bfs求出任意两点间的距离然后转换成tsp问题,用dfs解
- /*
- 题意:给一个 n*m的图,有一个机器人从一点开始清理垃圾,要求把所有的垃圾清理完,求最短的路径
- 思路:这个题可以先用bfs求出任意两点间的距离然后转换成tsp问题,用dfs解。
- 这个题还可以用状态压缩bfs写,但写了一次没过,再试试。
- */
- #include <cstdlib>
- #include <stdio.h>
- #include <string.h>
- #include <queue>
- #define INF 0x7fffffff
- #define N 22
- using namespace std;
- struct node
- {
- int x,y,step;
- }p[N*N],s,e;
- char map[N][N];
- int n,m,d[][]={,,,,,-,-,},used[N][N];
- int dis[N][N],ans,use[N],cnt;
- bool ok(int x,int y)
- {
- return x>=&&x<n&&y>=&&y<m&&map[x][y]!='x'&&!used[x][y];
- }
- int bfs()
- {
- memset(used,,sizeof(used));
- int i;
- queue<node> q;
- q.push(s);
- while(!q.empty())
- {
- node cur=q.front(),next;
- q.pop();
- for(i=;i<;i++)
- {
- next.x=cur.x+d[i][];
- next.y=cur.y+d[i][];
- next.step=cur.step+;
- if(ok(next.x,next.y))
- {
- used[next.x][next.y]=;
- if(next.x==e.x&&next.y==e.y)
- return next.step;
- q.push(next);
- }
- }
- }
- return INF;
- }
- void dfs(int s,int num,int length)
- {
- int j;
- if(num==&&ans>length)
- {
- ans=length;
- return ;
- }
- if(length>ans)
- return ;
- for(j=;j<cnt;j++)
- {
- if(dis[s][j]!=INF&&!use[j])
- {
- use[j]=;
- length+=dis[s][j];
- dfs(j,num-,length);
- num+;
- length-=dis[s][j];
- use[j]=;
- }
- }
- }
- int main()
- {
- int i, j, start, flag;
- while(scanf("%d%d",&m,&n)&&(n||m))
- {
- cnt=flag=;
- for(i=;i<n;i++)
- {
- scanf("%s",map[i]);
- for(j=;j<m;j++)
- {
- if(map[i][j]=='o'||map[i][j]=='*')
- {
- p[cnt].x=i,p[cnt].y=j;
- if(map[i][j]=='o')
- start=cnt;
- cnt++;
- }
- dis[i][j]=INF;
- }
- }
- //memset(dis,INF,sizeof(dis));
- for(i=;i<cnt;i++)
- for(j=i+;j<cnt;j++)
- {
- s=p[i],e=p[j],s.step=;
- dis[i][j]=dis[j][i]=bfs();
- if(dis[i][j]==INF)
- {
- flag=;
- break;
- }
- }
- /* for(i=0;i<cnt;i++)
- {
- for(j=0;j<cnt;j++)
- printf("%d\t",dis[i][j]);
- puts("");
- }*/
- if(flag)
- puts("-1");
- else
- {
- ans=INF;
- memset(use,,sizeof(use));
- use[start]=;
- dfs(start,cnt-,);
- printf("%d\n",ans);
- }
- }
- return ;
- }
状压 BFS
- #include <bits/stdc++.h>
- #define INF 0x3f3f3f3f
- using namespace std;
- struct NODE
- {
- int ni,nj,mask,len;
- NODE(){};
- NODE(int n_i,int n_j,int nmask,int nlen):
- ni(n_i),nj(n_j),mask(nmask),len(nlen){};
- };
- char G[][];
- int w,h,cnt,st_i,st_j;
- int vis[][][<<],flag[][];
- int mi[]={,,,-},mj[]={,-,,};
- bool bound(int i,int j) /// 判断是否越界
- {
- return (i>h||i<||j>w||j<);
- }
- bool OK(int mask) /// 判断垃圾是否被清理
- {
- for(int i=;i<cnt;i++)
- if(mask & (<<i)); /// 用mask二进制的各个位表示各个垃圾
- else return ;
- return ;
- }
- int BFS()
- {
- memset(vis,,sizeof(vis));
- int ans=INF;
- queue<NODE> q;
- q.push(NODE(st_i,st_j,,)); /// 构造函数的便利之处
- while(!q.empty())
- {
- NODE tmp=q.front(); q.pop();
- if(OK(tmp.mask)) /// 返回1表明垃圾清理光了 就更新ans值
- {
- ans=min(ans,tmp.len);
- continue;
- }
- if(vis[tmp.ni][tmp.nj][tmp.mask]) continue;
- /// 该点的mask状态已出现过 则忽略该点
- else vis[tmp.ni][tmp.nj][tmp.mask]=;
- /// 未出现过 则标记为已出现过
- for(int i=;i<;i++)
- {
- int newi=tmp.ni+mi[i],newj=tmp.nj+mj[i],newmask=tmp.mask;
- if(bound(newi,newj)||G[newi][newj]=='x') continue;
- /// 若越界或该点为墙 则忽略该点
- if(G[newi][newj]=='*')
- newmask=tmp.mask | (<<flag[newi][newj]);
- /* 假如目前是三号垃圾 更新状态
- 即若此时tmp.mask的二进制为011(第一二号垃圾已清除)
- newmask=011 | 1<<3=111(第一二三号垃圾已清除)
- 很明显 将垃圾状态压缩 用mask的二进制表示 */
- if(vis[newi][newj][newmask]) continue;
- /// 若该新点的该状态已出现过 则忽略该点 若无则放入队列
- q.push(NODE(newi,newj,newmask,tmp.len+));
- }
- }
- return ans==INF ? -:ans;
- }
- int main()
- {
- while(~scanf("%d%d",&w,&h)&&(w||h))
- {
- cnt=;
- for(int i=;i<=h;i++)
- for(int j=;j<=w;j++)
- {
- scanf(" %c",&G[i][j]);
- if(G[i][j]=='o') st_i=i,st_j=j; /// 记下所在位置
- else if(G[i][j]=='*') flag[i][j]=cnt++;
- /// 记下垃圾的位置 并为其编号 防止重复清扫
- }
- if(!cnt) printf("0\n");
- else printf("%d\n",BFS());
- }
- return ;
- }
Japan 2005 Domestic Cleaning Robot /// BFS 状压 二进制位运算 结构体内构造函数 oj22912的更多相关文章
- 孤岛营救问题 (BFS+状压)
https://loj.ac/problem/6121 BFS + 状压 写过就好想,注意细节debug #include <bits/stdc++.h> #define read rea ...
- hdu 5094 Maze (BFS+状压)
题意: n*m的迷宫.多多要从(1,1)到达(n,m).每移动一步消耗1秒.有P种钥匙. 有K个门或墙.给出K个信息:x1,y1,x2,y2,gi 含义是(x1,y1)与(x2,y2)之间有gi ...
- hdu 4771 Stealing Harry Potter's Precious (BFS+状压)
题意: n*m的迷宫,有一些格能走("."),有一些格不能走("#").起始点为"@". 有K个物体.(K<=4),每个物体都是放在& ...
- HDU-3681-Prison Break(BFS+状压DP+二分)
Problem Description Rompire is a robot kingdom and a lot of robots live there peacefully. But one da ...
- 【BZOJ 3049】【USACO2013 Jan】Island Travels BFS+状压DP
这是今天下午的互测题,只得了60多分 分析一下错因: $dis[i][j]$只记录了相邻的两个岛屿之间的距离,我一开始以为可以,后来$charge$提醒我有可能会出现来回走的情况,而状压转移就一次,无 ...
- HDU 5025:Saving Tang Monk(BFS + 状压)
http://acm.hdu.edu.cn/showproblem.php?pid=5025 Saving Tang Monk Problem Description <Journey to ...
- hdu 4856 Tunnels (bfs + 状压dp)
题目链接 The input contains mutiple testcases. Please process till EOF.For each testcase, the first line ...
- 【HDU 4771 Stealing Harry Potter's Precious】BFS+状压
2013杭州区域赛现场赛二水... 类似“胜利大逃亡”的搜索问题,有若干个宝藏分布在不同位置,问从起点遍历过所有k个宝藏的最短时间. 思路就是,从起点出发,搜索到最近的一个宝藏,然后以这个位置为起点, ...
- hdu 2209 bfs+状压
http://acm.hdu.edu.cn/showproblem.php?pid=2209 不知为啥有种直觉.会出状压+搜索的题,刷几道先 简单的BFS.状压表示牌的状态, //#pragma co ...
随机推荐
- opencv打开摄像头并新建窗口显示
几个程序使用的基本函数如下: ******************************************************************* cvCreateCameraCap ...
- C语言中的数据类型转换函数
头文件#include<stdlib.h> 1. 函数名: atof 功 能: 把字符串转换成浮点数 用 法: double atof(const char *nptr); 2.函数名: ...
- This inspection detects shadowing names defined in outer scopes.
错误信息:This inspection detects shadowing names defined in outer scopes. 检查到波浪处的单词已在函数外部定义. 解决:使用global ...
- python正则re
import reline = "Catsaresmarterthandogs"matchObj = re.match( r'(.*)are(\w{2})(.*)', line, ...
- vim与ctags/cscope的完美结合
1. 安装vim/ctags/cscope ctag 2. 在源码根目录下执行 sudo ctags -R . 会生成tags文件,里面包含着整个源码目录下的符号信息. 3. 直接到达某个符号(比 ...
- awesome mac
https://proxyman.app/ https://proxie.app/docs/#how-does-it-work https://github.com/kyleduo/TinyPNG4M ...
- Ubuntu 14.04 64位上安装wps office软件
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/tao_627/article/details/24179933 废话少说,仅仅给出方法供各位參考! ...
- pytest-mark跳过
import pytestimport sysenvironment='android' @pytest.mark.skipif(environment=="android",re ...
- (Struts2学习系列五)Struts2默认action
当我们访问项目下一个不存在的Action的时候,页面就会报错,404找不到资源,这样对用户来说是非常不友好的,所以我们设置一个默认的Action,当找不到对应Action的时候,就会跳转到默认Acti ...
- 如何恢复误删的OneNote页面
今天不小心把半个月的日记删掉了!(为了减少页面数量,每个月的日记会放在同一个页面上). 幸运的是OneNote有自动备份功能,喜极而泣. 操作方法来自微软支持 打开丢失了最近笔记的笔记本. 单击“文件 ...