HDU 3681 Prison Break 越狱(状压DP,变形)
题意:
给一个n*m的矩阵,每个格子中有一个大写字母,一个机器人从‘F’出发,拾取所有的开关‘Y’时便能够越狱,但是每走一格需要花费1点能量,部分格子为充电站‘G’,每个电站只能充1次电。而且部分格子为障碍'D'或者空格‘S’。机器人在开始时电池是满能量的,问电池容量至少为多少可以越狱?(1<=n,m<=14,充电站+开关的总个数<=15)
思路:
看错题了,以为充电站和开关的个数分别至多为14,其实是两种加起来14。
既然只有15个关键的格子,那么状压就有用了。假设每个点关键格必须走1次,那么就像可重复走的TSP了。但是充电站只能充1次,而且路过了也可以不充。所以,其实关键格只有那些“开关”,只要保证所有开关都收集全了,其他都无所谓。
具体做法,求出这15个格子(包括起点)的两两之间的距离(BFS就够了),相当于一个完全连通图。再二分答案,判断是否能够收集所有开关。判断能否收集开关,就相当于求所有点只能走1次的欧拉路径了,直接状态压缩来求,注意:两点间不一定可达,遇到充电站必须充满电。这样子对于一个格子具体走过了多少格已经没有关系了。
//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <deque>
#include <map>
#include <algorithm>
#include <vector>
#include <iostream>
#define pii pair<int,int>
#define INF 0x3f3f3f3f
#define LL long long
#define ULL unsigned long long
using namespace std;
const double PI = acos(-1.0);
const int N=;
int dp[<<][N], tag[N][N], vis[N][N], dis[N][N], n, m, egy;
char g[N][N]; struct node
{
int x,y,d;
node(){};
node(int x,int y,int d):x(x),y(y),d(d){};
};
inline bool istar(int x,int y){return tag[x][y]>;}
inline bool isok(int x,int y){ return (x>&&x<=n)&&(y>&&y<=m)&&g[x][y]!='D';}
inline int cmp(node a,node b){ return g[a.x][a.y]<g[b.x][b.y];}
bool binary(int cap)
{
memset(dp,-,sizeof(dp));
dp[][]=cap;
for(int s=; s<(<<n); s++)
{
for(int i=; i<=n; i++)
{
if( (s&(<<i-))== ) continue; //未走
for(int j=; j<=n; j++)
{
if( s&(<<j-) ) continue; //只能走1次
int add= j<=egy?cap:-;
if( dis[i][j]> && dp[s][i]>=dis[i][j] ) //前提要走得到那个位置
dp[s|(<<j-)][j]=max(dp[s|(<<j-)][j], max(dp[s][i]-dis[i][j],add));
}
}
}
int mod=(<<n)-(<<egy)+, ans=-INF;
for(int s=; s<(<<n); s++)
{
if( (s&mod)==mod )
{
for(int i=; i<=n; i++)
ans=max(ans, dp[s][i]);
}
}
return ans>=;
} deque<node> que;
void BFS(int x,int y) //求最短路
{
memset(vis,,sizeof(vis));
que.clear();
que.push_back(node(x,y,));
vis[x][y]=true;
while(!que.empty())
{
node t=que.front();que.pop_front();
if( istar(t.x,t.y) ) //记录最短路
dis[tag[x][y]][tag[t.x][t.y]]=t.d;
if(isok(t.x-,t.y)&&!vis[t.x-][t.y])
{
que.push_back(node(t.x-,t.y,t.d+) );
vis[t.x-][t.y]=true;
}
if(isok(t.x+,t.y)&&!vis[t.x+][t.y])
{
que.push_back(node(t.x+,t.y,t.d+) );
vis[t.x+][t.y]=true;
}
if(isok(t.x,t.y-)&&!vis[t.x][t.y-])
{
que.push_back(node(t.x,t.y-,t.d+) );
vis[t.x][t.y-]=true;
}
if(isok(t.x,t.y+)&&!vis[t.x][t.y+])
{
que.push_back(node(t.x,t.y+,t.d+) );
vis[t.x][t.y+]=true;
}
}
} int cal()
{
vector<node> vect; //关键点
for(int i=; i<=n; i++) //编号
for(int j=; j<=m; j++)
if(g[i][j]!='S'&&g[i][j]!='D')
vect.push_back(node(i,j,)); sort(vect.begin(), vect.end(), cmp); //按字典序排序
for(int i=; i<vect.size(); i++) //编号
tag[vect[i].x][vect[i].y]=i+; egy=;
for(int i=; i<vect.size(); i++)
{
if(g[vect[i].x][vect[i].y]=='G') egy++;
BFS(vect[i].x,vect[i].y); //计算最短路
}
n=vect.size();
if(egy==n) return ; //无开关?
if(!binary()) return -; //不可达 int L=, R=;
while(L<R) //二分答案
{
int mid=R-(R-L+)/;
if( binary(mid) ) R=mid;
else L=mid+;
}
return R;
} int main()
{
//freopen("input.txt","r",stdin);
while(scanf("%d%d",&n,&m), n+m)
{
memset(tag,,sizeof(tag));
memset(dis,-,sizeof(dis)); for(int i=; i<=n; i++) scanf("%s",g[i]+);
printf("%d\n",cal());
}
return ;
}
AC代码
HDU 3681 Prison Break 越狱(状压DP,变形)的更多相关文章
- HDU 3681 Prison Break(状压DP + BFS)题解
题意:一张图,F是起点,Y是必须要到的点,D不能走,G可以充电.可以往四个方向走,每走一步花费一个电,走到G可以选择充满电或者不充,每个G只能充一次.问你走遍Y的最小初始点亮.number(G) + ...
- HDU 3681 Prison Break(状态压缩dp + BFS)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3681 前些天花时间看到的题目,但写出不来,弱弱的放弃了.没想到现在学弟居然写出这种代码来,大吃一惊附加 ...
- HDU-3681-Prison Break(BFS+状压DP+二分)
Problem Description Rompire is a robot kingdom and a lot of robots live there peacefully. But one da ...
- HDU 6149 Valley Numer II 状压DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6149 题意:中文题目 解法:状压DP,dp[i][j]代表前i个低点,当前高点状态为j的方案数,然后枚 ...
- HDU 5434 Peace small elephant 状压dp+矩阵快速幂
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant Accepts: 38 Submissions: ...
- HDU 1074 Doing Homework(状压DP)
第一次写博客ORZ…… http://acm.split.hdu.edu.cn/showproblem.php?pid=1074 http://acm.hdu.edu.cn/showproblem.p ...
- HDU 4906 Our happy ending (状压DP)
HDU 4906 Our happy ending pid=4906" style="">题目链接 题意:给定n个数字,每一个数字能够是0-l,要选当中一些数字.然 ...
- HDU 1074 Doing Homework (状压dp)
题意:给你N(<=15)个作业,每个作业有最晚提交时间与需要做的时间,每次只能做一个作业,每个作业超出最晚提交时间一天扣一分 求出扣的最小分数,并输出做作业的顺序.如果有多个最小分数一样的话,则 ...
- HDU 4568 Hunter 最短路+状压DP
题意:给一个n*m的格子,格子中有一些数,如果是正整数则为到此格子的花费,如果为-1表示此格子不可到,现在给k个宝藏的地点(k<=13),求一个人从边界外一点进入整个棋盘,然后拿走所有能拿走的宝 ...
随机推荐
- Linux命令总结_命令执行顺序
有时候,我们需要一个命令执行完之后再去执行另一个命令,使用 &&和 ||可以完成 这样的功能,相应的命令可以是系统命令或shell脚本 Shell还提供了在当前shell或子shell ...
- MAF框架的使用限制
虽然MAF实现了插件式开发,动态热插拨,AppDomain隔离等诸多优点,但是正因为它复杂的功能机制也带来了很多其它方面的使用限制,下面列出官方给出的MAF框架的使用限制. 1) 在应用主程序显示的插 ...
- day1 java基础回顾-集合
1.集合 1.1 集合的类型与各自的特性 ---|Collection: 单列集合 ---|List: 有存储顺序, 可重复 ---|ArrayList: 数组实现, 查找快, 增删慢 由于是数组实现 ...
- 3. 关于sql注入的综合题
关于sql注入的综合题 ----------南京邮电大学ctf : http://cms.nuptzj.cn/ 页面上也给了好多信息: 根据这个sm. ...
- 数据可视化系列--svg入门基础(一)
一.前言 1.SVG(Scalable Vector Graphics)可伸缩矢量图形 特点: (1)使用xml格式来定义图形: (2)用来定义web上的使用的矢量图: (3)改变图像尺寸,图片质量不 ...
- 洛谷U3348 A2-回文数
U3348 A2-回文数 题目背景 方方方很喜欢回文数,于是就有了一道关于回文数的题目. 题目描述 求从小到大第n(1<=n<=10^18)个回文数. 注释:出题人认为回文数不包括0. 输 ...
- Codevs 1688 求逆序对(权值线段树)
1688 求逆序对 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 给定一个序列a1,a2,…, ...
- Java基础--面向对象以及相关知识
一. 面向对象特征与原则 1.三大特征:封装.继承.多态. (1)封装:将客观的事物封装成抽象的类,封装代码逻辑,并通过访问控制符来控制访问的方式,从而保护程序(使用反射时,可以获取对象的私有方法和成 ...
- 01分数规划初探?!By cellur925
都要\(NOIp\)了为啥我还在看这种玄学玩意..... \(01\)分数规划:这是一个问题模型\(qwq\),一般是在求\[\frac{\sum_{i=1}^{n} a_i*x_i}{\sum_{i ...
- 长春理工大学第十四届程序设计竞赛(重现赛)I.Fate Grand Order
链接:https://ac.nowcoder.com/acm/contest/912/I 题意: Fate Grand Order是型月社发行的角色扮演类手机游戏,是著名的氪金抽卡"垃圾&q ...