蒜头君救人 状压DP
蒜头君救人
题目描述
蒜头君是一个乐于助人的好孩子,这天他所在的乡村发生了洪水,有多名村民被困于孤岛上,于是蒜头君决定去背他们离开困境,假设蒜头君所在的村子是 n×m n×m 的网格,网格中.号代表平地,#号代表该地已被洪水淹没,A、B……等大写字母表示该地有村民被困,s代表蒜头君的起点,t代表蒜头君的终点。
蒜头君的初始速度为 k 秒一格,他每次可以向上下左右 4 个方向中的一个移动 1 格。在背上一个村民后,他的速度可能会降低,也可能会加快,但他的速度不能快于 1 秒每格,那么蒜头君想知道,他最快需要多长时间将所有村民救出?
注意:不能在终点以外的地方放下村民;可以同时背多个村民。
输入格式
第一行 3 个正整数 n,m(1≤n,m≤10),k n,m(1 \le n,m \le 10),k,分别表示村庄长度、宽度、蒜头君初始速度。
接下来 n n行,每行一个长度为mm 的字符串,表示村庄的地形,字符串意义如上所述。
接下来若干行,每行一个大写字母、一个整数,表示该编号的村民会使 k k 增加 / 减少多少。行数等同于地形中大写字母的个数。大写字母按字典序,即A、B、C的顺序排列,保证前后两行的字母是连续的,村民个数小于等于 10。
输出格式
输出 1 个整数,表示最小用时。
样例输入
4 4 2
s.##
..A#
.B##
…t
A -3
B 4
样例输出
17
数据规模这么小,不是搜索就是状压。
标程给出的是三进制状压DP,但是这样做使得位运算的优势不复存在了。所以时间复杂度其实也只是理性愉悦,提取某一位常数很大。而且也增加了编程复杂度。
事实上二进制状压DP是可以的,并不会达到 O(4cntcnt2) O(4^{cnt}cnt^2)的复杂度,而且跑得很快。
定义状态 f[S1][S2][p] f[S_1][S_2][p]表示背着的村民状态为 S1 S_1,已经到终点的村民为 S2 S_2,蒜头君处在 p p位置(pp只取初始状态下村民的位置、终点位置),那么显然有状态转移:
f[S_1|(1
(x\notin S_2,x\in S_1,y\notin S_2,y\notin S_1)
f[S_1 xor T][S_2|T][en]=min(f[S_1 xor T][S_2|T][en],f[S_1][S_2][en])
(T\in S_1,en为终点)
V[S] V[S]表示在背着的村民状态为 S S下的速度,dis(x,y)dis(x,y)表示在原图上 x,y x,y的距离。都可以预处理出来。下面的代码采用的是floyd求距离,当然也可以用BFS。
上述两式分别表示到一个地方接村民、在终点放村民。如果不用记忆化搜索的形式,注意循环顺序。
那么为什么跑得很快呢?因为在这样的定义下, S1 S_1与 S2 S_2是不能有交集的,这样显然不可能的情况在循环里判断一下就可以了,实际上可能合法的情况只有 3cnt 3^{cnt}种。再加上 x,y x,y与两个集合间的关系,循环执行的次数不会特别多。
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;int N,M,K,dx[4]={0,0,1,-1},dy[4]={-1,1,0,0};
int Map[105][105],pos[15],id[15][15],tot,v[15];
int f[1234][1234][15],V[1234],U,inf;
char s[15][15];int main()
{int i,j,k,x,y,tx,ty,St;char ch[3];scanf("%d%d%d",&N,&M,&K);for(i=1;i<=N;i++)scanf("%s",&s[i][1]);while(scanf("%s%d",ch,&x)!=EOF)v[++v[0]]=x;for(i=1;i<=N;i++)for(j=1;j<=M;j++)id[i][j]=++tot;for(i=1;i<=tot;i++)for(j=1;j<=tot;j++)Map[i][j]=1e9;for(i=1;i<=tot;i++)Map[i][j]=0;for(i=1;i<=N;i++)for(j=1;j<=M;j++){if(s[i][j]=='#')continue;x=i;y=j;for(k=0;k<4;k++){tx=x+dx[k];ty=y+dy[k];if(tx&&ty&&tx<=N&&ty<=M&&s[tx][ty]!='#'){int a=id[x][y],b=id[tx][ty];Map[a][b]=1;}}}for(k=1;k<=tot;k++)for(i=1;i<=tot;i++)for(j=1;j<=tot;j++)Map[i][j]=min(Map[i][j],Map[i][k]+Map[k][j]);//floyd预处理距离for(i=1;i<=N;i++)for(j=1;j<=M;j++){if(s[i][j]=='s')St=id[i][j];if(s[i][j]=='t')pos[v[0]+1]=id[i][j];if(s[i][j]>='A'&&s[i][j]<='Z')pos[s[i][j]-'A'+1]=id[i][j];}U=(1<<v[0])-1;V[0]=K;for(i=1;i<=U;i++){int tmp=0;for(j=1;j<=v[0];j++)if((i>>j-1)&1)tmp+=v[j];V[i]=tmp+K;if(V[i]<1)V[i]=1;}//预处理Vmemset(f,60,sizeof(f));for(i=1;i<=v[0];i++)f[1<<i-1][0][i]=Map[St][pos[i]]*K;f[0][0][v[0]+1]=Map[St][pos[v[0]+1]]*K;inf=f[0][0][0];for(j=0;j<U;j++)for(i=0;i<=U;i++){if(i&j)continue;//在这样的定义下,不能有交集for(x=1;x<=v[0]+1;x++){if(f[i][j][x]==inf||(x<=v[0]&&(!((i>>x-1)&1))))continue;for(y=1;y<=v[0];y++){if((i>>y-1)&1||(j>>y-1)&1)continue;if(f[i|(1<<y-1)][j][y]>f[i][j][x]+V[i]*Map[pos[x]][pos[y]])f[i|(1<<y-1)][j][y]=f[i][j][x]+V[i]*Map[pos[x]][pos[y]];}y=v[0]+1;if(f[i][j][y]>f[i][j][x]+V[i]*Map[pos[x]][pos[y]])f[i][j][y]=f[i][j][x]+V[i]*Map[pos[x]][pos[y]];}for(x=i;x;x=x-1&i)f[i^x][j|x][v[0]+1]=min(f[i^x][j|x][v[0]+1],f[i][j][v[0]+1]);//枚举子集}printf("%d",f[0][U][v[0]+1]);
}
蒜头君救人 状压DP相关推荐
- UVa 11825 (状压DP) Hackers' Crackdown
这是我做状压DP的第一道题,状压里面都是用位运算来完成的,只要耐下心来弄明白每次位运算的含义,还是容易理解的. 题意: 有编号为0~n-1的n台服务器,每台都运行着n中服务,每台服务器还和若干台其他服 ...
- 「CTSC2017」吉夫特(Gift) (Lucas定理,状压DP)
题面 链接 简单的题目,既是礼物,也是毒药. B 君设计了一道简单的题目,准备作为 gift 送给大家. 输入一个长度为 n n n 的数列 a 1 , a 2 , ⋯ , a n a_1, a_2, ...
- POJ 1038 Bugs Integrated Inc (复杂的状压DP)
\(POJ~1038~~*Bugs~Integrated~Inc:\) (复杂的状压DP) \(solution:\) 很纠结的一道题目,写了大半天,就想练练手,结果这手生的.其实根据之前那道炮兵阵地 ...
- codeforces 8C. Looking for Order 状压dp
题目链接 给n个物品的坐标, 和一个包裹的位置, 包裹不能移动. 每次最多可以拿两个物品, 然后将它们放到包里, 求将所有物品放到包里所需走的最小路程. 直接状压dp就好了. #include < ...
- UVA10296 Jogging Trails(中国邮递员问题)(欧拉回路、一般图最大权匹配 / 状压DP)
整理的算法模板合集: ACM模板 目录 思路 UVA10296 Jogging Trails 题目翻译: 给你n个点,m条无向边,每条边有一定的距离数值,构造成一个连通图.问从任意一点出发,遍历所有的 ...
- POJ 2411 Mondriaan‘s Dream(最清楚好懂的状压DP讲解)(连通性状态压缩DP)
poj 2411 Mondriaan's Dream(最清晰的状压DP解析) 闫氏DP大法好 我们这里是一列一列地来,因为是一个棋盘性的状态压缩DP,从哪个方向都一样 摆放的小方格总方案数 等价于 横 ...
- 【每日DP】day2、P1879 [USACO06NOV]Corn Fields G玉米地(状压DP模板题)难度⭐⭐⭐★
昨天的每日DP我还在写01背包,今天就到状压DP了,真刺激. P1879 [USACO06NOV]Corn Fields G 题目链接 输入 2 3 1 1 1 0 1 0 输出 9 一道简单的状压D ...
- hdu 4778 Gems Fight! 状压dp
转自wdd :http://blog.csdn.net/u010535824/article/details/38540835 题目链接:hdu 4778 状压DP 用DP[i]表示从i状态选到结束得 ...
- 【洛谷 P1896】[SCOI2005]互不侵犯(状压dp)
题目链接 题意:在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 这是道状压\(DP\)好题啊.. ...
最新文章
- 厉害!重庆参加马拉松赛人数7年翻10倍,今年区县马拉松赛事将大增
- 自学python找工作工资-大四应届毕业生,学了两个月Python,找工作感觉好难啊?...
- Linux-xargs命令
- nginx源码分析--使用GDB调试
- day11-元组与字典
- LAB Color Space
- java工程师面试题:如何判断链表有环?
- SQL Server 2005利用分区对海量数据的处理
- Fedora 33 配置Samba 服务器
- Android手机游戏开发入门教程
- 一 . 暴力破解与实用性优先
- spilt的用法小结
- 20221115使用google文档翻译SRT格式的字幕
- matlab独立t样本检验,matlab与单样本t检验
- 医学影像设备学_【技士/师证考试宝典】第四篇 医学影像设备学CR 11
- smb1文件共享不安全不能连接文件共享
- cpu 占用过高排查
- matlab近红外光谱曲线,Matlab关于偏最小二乘法应用于近红外光谱分析的问题
- AST反混淆实战-经典ob混淆
- ​草莓熊python绘图(春节版,圣诞倒数雪花版)附源代码
热门文章
- B. Kevin and Permutation codeforces1754B
- 《康熙大帝》和《雍正皇帝》EXE电子书
- 第十五天学习HTML、CSS
- (文末送书)一文读懂 Web 安全
- Gen8 ESXi 6.5 硬盘RDM 直通
- STM32 |显示:API is not found, corresponding pack is missing or not selected
- Persistence 与HibernatePersistence详解
- 十天让你网站ip流量从十增至一万
- python创建虚拟环境报错_python 创建虚拟环境时报错OSError, setuptools下载失败
- OwnCloud搭建自己的私有云盘