题意:

  给一个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,变形)的更多相关文章

  1. HDU 3681 Prison Break(状压DP + BFS)题解

    题意:一张图,F是起点,Y是必须要到的点,D不能走,G可以充电.可以往四个方向走,每走一步花费一个电,走到G可以选择充满电或者不充,每个G只能充一次.问你走遍Y的最小初始点亮.number(G) + ...

  2. HDU 3681 Prison Break(状态压缩dp + BFS)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3681 前些天花时间看到的题目,但写出不来,弱弱的放弃了.没想到现在学弟居然写出这种代码来,大吃一惊附加 ...

  3. HDU-3681-Prison Break(BFS+状压DP+二分)

    Problem Description Rompire is a robot kingdom and a lot of robots live there peacefully. But one da ...

  4. HDU 6149 Valley Numer II 状压DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6149 题意:中文题目 解法:状压DP,dp[i][j]代表前i个低点,当前高点状态为j的方案数,然后枚 ...

  5. HDU 5434 Peace small elephant 状压dp+矩阵快速幂

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant  Accepts: 38  Submissions: ...

  6. HDU 1074 Doing Homework(状压DP)

    第一次写博客ORZ…… http://acm.split.hdu.edu.cn/showproblem.php?pid=1074 http://acm.hdu.edu.cn/showproblem.p ...

  7. HDU 4906 Our happy ending (状压DP)

    HDU 4906 Our happy ending pid=4906" style="">题目链接 题意:给定n个数字,每一个数字能够是0-l,要选当中一些数字.然 ...

  8. HDU 1074 Doing Homework (状压dp)

    题意:给你N(<=15)个作业,每个作业有最晚提交时间与需要做的时间,每次只能做一个作业,每个作业超出最晚提交时间一天扣一分 求出扣的最小分数,并输出做作业的顺序.如果有多个最小分数一样的话,则 ...

  9. HDU 4568 Hunter 最短路+状压DP

    题意:给一个n*m的格子,格子中有一些数,如果是正整数则为到此格子的花费,如果为-1表示此格子不可到,现在给k个宝藏的地点(k<=13),求一个人从边界外一点进入整个棋盘,然后拿走所有能拿走的宝 ...

随机推荐

  1. HDU 3572 Task Schedule (最大流)

    C - Task Schedule Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u S ...

  2. Linear Algebra - Determinant(基础)

    1. 行列式的定义 一阶行列式: \[ \begin{vmatrix} a_1 \end{vmatrix} = a_1 \] 二阶行列式: \[ \begin{vmatrix} a_{11} & ...

  3. [openjudge] 1455:An Easy Problem 贪心

    描述As we known, data stored in the computers is in binary form. The problem we discuss now is about t ...

  4. js组件化(转载)

    今天想着开始封装自己的UI库和组件库,从网上看到一篇很好的关于js组件化的文章,现在分享一下. 转载地址:https://blog.csdn.net/Prince_fmx/article/detail ...

  5. python2与python3 版本区别

    目录 编码 输入输出 中文 除法 长整形 内置函数map xrange init reduce 字符串类型 dict字典 经典类 新式类 未完待补充 编码 python2默认编码器为ascii码(只支 ...

  6. Python读写Excel表格

    最近在做一些数据处理和计算的工作,因为数据是以.CSV格式保存的,因此刚开始直接用Excel来处理. 但是做着做着发现重复的劳动,其实并没有多大的意义,于是就想着写个小工具帮着处理. 以前正好在一本书 ...

  7. 6.Python初窥门径(小数据池,集合,深浅拷贝)

    Python(小数据池,集合,深浅拷贝) 一.小数据池 什么是小数据池 小数据池就是python中一种提高效率的方式,固定数据类型,使用同一个内存地址 小数据池 is和==的区别 == 判断等号俩边的 ...

  8. 用SqlDataAdapter与datagridview配合实现快速CRUD

    private void btnSave_Click(object sender, EventArgs e) { //把DataGridView的修改的数据保存到数据库中去. string connS ...

  9. WEB安全字体(Web Safe Fonts)-网页设计用什么字体兼容性好?

    效果:http://sandbox.runjs.cn/show/qgdljvh4 1 Arial微软公司的网页核心字体之一,最常用的sans serif字体,当字号很小时不容易阅读.但是,大写的“I” ...

  10. myeclipse 最佳设置

    http://www.cnblogs.com/wuyifu/p/3593035.html