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),求一个人从边界外一点进入整个棋盘,然后拿走所有能拿走的宝 ...
随机推荐
- [poj1986]Distance Queries(LCA)
解题关键:LCA模板题 复杂度:$O(n\log n)$ #pragma comment(linker, "/STACK:1024000000,1024000000") #incl ...
- 【机器学习】迭代决策树GBRT(渐进梯度回归树)
一.决策树模型组合 单决策树C4.5由于功能太简单,并且非常容易出现过拟合的现象,于是引申出了许多变种决策树,就是将单决策树进行模型组合,形成多决策树,比较典型的就是迭代决策树GBRT和随机森林RF. ...
- 我对微信小程序的一些认识
一. 什么是微信小程序. 微信小程序是指微信公众平台小程序,小程序可以帮助开发者快速的开发小程序,小程序可以在微信内被便捷地获取和传播:是不需要下载和安装既可以使用的应用小程序,是和原有的三种微信公众 ...
- SCUT - 157 - CC和他的GCD - 容斥原理
https://scut.online/p/157 鉴于多年(都没几个月)搞数论的经验,这种时候枚举g肯定是对的. 那么肯定是要莫比乌斯函数作为因子,因为很显然? 但是为什么要搞个负的呢?其实是因为这 ...
- C++ STL vector使用总结
vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库.vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说vect ...
- 3dmax室内设计,建筑视频
第一教程篮球场 http://video.1kejian.com/video/?30800-0-1.html 第一课 元素级别-flip反转(直接看模型里面) 第二课 alt+r = ring crt ...
- Java进程占用内存过高,排查解决方法
最近收到邮件报警,说内存使作率达到84%.如下图: 解决方法: A:可能是代码原因导致的问题: 1.使用命令:top 查看当前进程的状态 2.从上图可以看到PID:916的java进程占用内存较大.定 ...
- C# Func与Action总结
Action:无参数无返回值委托. Action<T>:泛型委托,无返回值,根据输入参数的个数不同有十六个重载. Func< out T>:无输入参数,有返回值. Func&l ...
- 洛谷1373(dp)
常规线性dp,需要时就加一维.\(dp[i][j][t][s]\)表示在点\((i,j)\)时瓶子里剩\(t\)且为\(s\)走(0代表小a,1代表uim)时的方案数. de了半天发现是初次尝试的快速 ...
- hdu1494 跑跑卡丁车(动态规划)
Description 跑跑卡丁车是时下一款流行的网络休闲游戏,你可以在这虚拟的世界里体验驾驶的乐趣.这款游戏的特别之处是你可以通过漂移来获得一种 加速卡,用这种加速卡可以在有限的时间里提高你的速度. ...