计蒜客模拟赛D2T3 蒜头君救人:用bfs转移状压dp
题目链接:https://nanti.jisuanke.com/t/16444
题意:
蒜头君是一个乐于助人的好孩子,这天他所在的乡村发生了洪水,有多名村民被困于孤岛上,于是蒜头君决定去背他们离开困境,假设蒜头君所在的村子是n*m的网格,网格中.号代表平地,#号代表该地已被洪水淹没,A、B……等大写字母表示该地有村民被困,s代表蒜头君的起点,t代表蒜头君的终点。
蒜头君的初始速度为 k秒一格,他每次可以向上下左右4个方向中的一个移动1格。在背上一个村民后,他的速度可能会降低,也可能会加快,但他的速度不能快于1秒每格,那么蒜头君想知道,他最快需要多长时间将所有村民救出?
注意:不能在终点以外的地方放下村民;可以同时背多个村民。
题解:
用dp[state][x][y]表示现在在(x , y)这个点,村民的状态为state。state是一个三进制数,每一位对应一个村民,0表示村民还在原地,1表示正在背着这个村民,2表示这个村民已经到达终点。
显然,应该先枚举村民状态state,再枚举当前位置(x , y)。但本题和一般的网格dp不同,起点并不一定在左上角(1 , 1)处,而且并不是只能走右和下两个方向,因此本题需要从起点开始bfs,对于每一个被更新dp值的状态,都需要加入队列中。
下面考虑如何转移。
如果当前地点为'.'(平地),那么state不变,向上下左右四个方向转移(不能是'#'),dp[state][...][...](上下左右) = min(dp[state][...][...] , dp[state][x][y] + cal_spd(state)),cal_spd(state)计算的是在当前状态时自己的速度。
如果当前地点为大写字母(有村民要救),并且当前state中这个村民还在原地,那么可以背上这个村民,dp[state_pick][x][y] = min(dp[state_pick][x][y] , dp[state][x][y]),state_pick为在当前state下再背上这个村民时的状态。
如果现在在终点t,很明显只有两种选择,一种是放下所有会让我减速的村民(能让我加速的村民肯定要一直背到底),一种是放下全部的村民(结束救人)。两种转移后的状态分别为state_part和state_all,那么dp[state_part][x][y] = min(dp[state_part][x][y] , dp[state][x][y]),dp[state_all][x][y] = min(dp[state_all][x][y] , dp[state][x][y])。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <ctype.h> 5 #include <queue> 6 #define MAX_N 15 7 #define MAX_S 60000 8 #define MAX_A 30 9 #define INF 10000000 10 11 using namespace std; 12 13 const int POW[]={1,3,9,27,81,243,729,2187,6561,19683,59049,177147,531441}; 14 15 struct Coor 16 { 17 int x; 18 int y; 19 Coor(int _x,int _y) 20 { 21 x=_x; 22 y=_y; 23 } 24 Coor(){} 25 }; 26 27 struct sta 28 { 29 int state; 30 int x; 31 int y; 32 sta(int _state,int _x,int _y) 33 { 34 state=_state; 35 x=_x; 36 y=_y; 37 } 38 sta(){} 39 }; 40 41 int n,m,k; 42 int cnt=0; 43 int spd[MAX_A]; 44 int dp[MAX_S][MAX_N][MAX_N]; 45 char c[MAX_N][MAX_N]; 46 bool vis[MAX_S][MAX_N][MAX_N]; 47 Coor start; 48 Coor over; 49 queue<sta> q; 50 51 inline int update(int &v,int k,int a) 52 { 53 return v=v-((v/POW[k])%3)*POW[k]+a*POW[k]; 54 } 55 56 inline int query(int v,int k) 57 { 58 return (v/POW[k])%3; 59 } 60 61 void read() 62 { 63 cin>>n>>m>>k; 64 for(int i=1;i<=n;i++) 65 { 66 for(int j=1;j<=m;j++) 67 { 68 cin>>c[i][j]; 69 if(c[i][j]=='s') start=Coor(i,j); 70 if(c[i][j]=='t') over=Coor(i,j); 71 if(isupper(c[i][j])) cnt++; 72 } 73 } 74 for(int i=0;i<cnt;i++) 75 { 76 char ch; 77 int speed; 78 cin>>ch>>speed; 79 spd[i]=speed; 80 } 81 } 82 83 int cal_spd(int state) 84 { 85 int sum=k; 86 for(int i=0;i<cnt;i++) 87 { 88 int val=query(state,i); 89 if(val==1) sum+=spd[i]; 90 } 91 return sum>=1?sum:1; 92 } 93 94 bool is_legal(int x,int y) 95 { 96 return c[x][y]!='#' && x>0 && x<=n && y>0 && y<=m; 97 } 98 99 int set_part(int state) 100 { 101 for(int i=0;i<cnt;i++) 102 { 103 if(spd[i]<=0) continue; 104 int val=query(state,i); 105 if(val==1) update(state,i,2); 106 } 107 return state; 108 } 109 110 int set_all(int state) 111 { 112 for(int i=0;i<cnt;i++) 113 { 114 int val=query(state,i); 115 if(val==1) update(state,i,2); 116 } 117 return state; 118 } 119 120 int pick_up(int state,int k) 121 { 122 return update(state,k,1); 123 } 124 125 void init_dp() 126 { 127 for(int state=0;state<POW[cnt];state++) 128 { 129 for(int i=1;i<=n;i++) 130 { 131 for(int j=1;j<=m;j++) 132 { 133 dp[state][i][j]=INF; 134 } 135 } 136 } 137 dp[0][start.x][start.y]=0; 138 } 139 140 sta get_front() 141 { 142 sta now=q.front(); 143 q.pop(); 144 vis[now.state][now.x][now.y]=false; 145 return now; 146 } 147 148 void insert(sta now) 149 { 150 if(vis[now.state][now.x][now.y]) return; 151 q.push(now); 152 vis[now.state][now.x][now.y]=true; 153 } 154 155 void bfs(sta start) 156 { 157 memset(vis,false,sizeof(vis)); 158 insert(start); 159 while(!q.empty()) 160 { 161 sta now=get_front(); 162 int x=now.x; 163 int y=now.y; 164 int state=now.state; 165 int speed=cal_spd(state); 166 if(is_legal(x+1,y) && dp[state][x+1][y]>dp[state][x][y]+speed) 167 { 168 dp[state][x+1][y]=dp[state][x][y]+speed; 169 insert(sta(state,x+1,y)); 170 } 171 if(is_legal(x-1,y) && dp[state][x-1][y]>dp[state][x][y]+speed) 172 { 173 dp[state][x-1][y]=dp[state][x][y]+speed; 174 insert(sta(state,x-1,y)); 175 } 176 if(is_legal(x,y+1) && dp[state][x][y+1]>dp[state][x][y]+speed) 177 { 178 dp[state][x][y+1]=dp[state][x][y]+speed; 179 insert(sta(state,x,y+1)); 180 } 181 if(is_legal(x,y-1) && dp[state][x][y-1]>dp[state][x][y]+speed) 182 { 183 dp[state][x][y-1]=dp[state][x][y]+speed; 184 insert(sta(state,x,y-1)); 185 } 186 if(c[x][y]=='t') 187 { 188 int state_part=set_part(state); 189 if(dp[state_part][x][y]>dp[state][x][y]) 190 { 191 dp[state_part][x][y]=dp[state][x][y]; 192 insert(sta(state_part,x,y)); 193 } 194 int state_all=set_all(state); 195 if(dp[state_all][x][y]>dp[state][x][y]) 196 { 197 dp[state_all][x][y]=dp[state][x][y]; 198 insert(sta(state_all,x,y)); 199 } 200 } 201 if(isupper(c[x][y])) 202 { 203 int state_pick=pick_up(state,c[x][y]-'A'); 204 if(dp[state_pick][x][y]>dp[state][x][y]) 205 { 206 dp[state_pick][x][y]=dp[state][x][y]; 207 insert(sta(state_pick,x,y)); 208 } 209 } 210 } 211 } 212 213 void solve() 214 { 215 init_dp(); 216 bfs(sta(0,start.x,start.y)); 217 } 218 219 void print() 220 { 221 cout<<dp[POW[cnt]-1][over.x][over.y]<<endl; 222 } 223 224 int main() 225 { 226 read(); 227 solve(); 228 print(); 229 }
转载于:https://www.cnblogs.com/Leohh/p/7268458.html
计蒜客模拟赛D2T3 蒜头君救人:用bfs转移状压dp相关推荐
- 计蒜客模拟赛D1T3 蒜头君的坐骑:用dfs转移dp
题目链接:https://nanti.jisuanke.com/t/16447 题意: 蒜头君有一只坐骑,人马. 一天,蒜头君骑着他的坐骑走上了一片n*m的大荒野,一开始时,蒜头君在(1,1)点,他要 ...
- 2020蓝桥杯B 组省赛计蒜客模拟赛(一)题解
2020蓝桥杯省赛 B 组计蒜客模拟赛(一)目录 试题 A:有趣的数字(结果填空) 试题 B:爬楼梯(结果填空) 试题 C:七巧板(结果填空) 试题 D:苹果(结果填空) 试题 E:方阵(结果填空) ...
- 【计蒜客模拟赛系列】-计蒜客2021年8月普及组模拟赛
提前:本文中部分代码和思路有借鉴或摘抄计蒜客官方题解 赛后总结 本次模拟赛的难度总算正常了些 个人战绩: 220/400,排名61 ,太弱了,一大堆AK爷 题目质量评价: 题目相比CSP-J还是简单了 ...
- 计蒜客模拟赛5-礼物盒
小y 有一个宽度为 100cm,高度为 20cm,深度为 1cm 的柜子,如下图. 小y 还有 36个礼物盒,他们的深度都为 1cm. 他们对应的宽度和高度如下,单位(cm). 11 3 8 12 1 ...
- 计蒜客模拟赛7礼品盒
第七题 小y 有一个宽度为 100cm,高度为 20cm,深度为 1cm 的柜子,如下图. 小y 还有 3636 个礼物盒,他们的深度都为 1cm. 他们对应的宽度和高度如下,单位(cm). 现在小y ...
- YbtOJ#20070-[NOIP2020模拟赛B组Day5]诗人小K【状压dp】
正题 题目链接:http://noip.ybtoj.com.cn/contest/102/problem/4 题目大意 求有多少个长度为nnn的序列aaa满足1≤ai≤101\leq a_i\leq ...
- 糖果(2019第十届蓝桥杯省赛C++A组I题) 解题报告(状压dp) Apare_xzc
糖果(2019第十届蓝桥杯省赛C++A组I题) 解题报告(状压dp) xzc 2019/4/5 试题 I: 糖果 时间限制: 1.0s 内存限制: 256.0MB 本题总分:25分 [问题描述] ...
- 牛客网 小白月赛4 D-郊区春游 最短路+状压dp
链接: https://www.nowcoder.com/acm/contest/134/D来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524 ...
- Nise-Anti-AK Problem 计蒜客网络赛
水题 Description: Peppa has been learning math recently, he is trapped by a easy problem. He is given ...
- 【计蒜客 - 蓝桥训练】修建公路(贪心,或运算,dp)
题干: 蒜头国有 nn 座城市,编号分别为 0,1,2,3,\ldots,n-10,1,2,3,-,n−1.编号为 xx 和 yy 的两座城市之间如果要修高速公路,必须花费 x|yx∣y 个金币,其中 ...
最新文章
- HTTP的KeepAlive是开启还是关闭?
- Educational Codeforces Round 2 B. Queries about less or equal elements
- linux cpu占用100原因查询,如何根据查询异常时间节点和连接进而确定CPU使用率100%的原因...
- android手势识别
- WIN10的IE错误代码inet_e_resource_not_found解决办法
- 平行四边形的特殊性质
- 小程序 | 云函数获取用户openid
- (138)System Verilog覆盖率目标设置
- python安装mysqldb模块_python MysqlDb模块安装及其使用详解
- java实验报告2013_java实验报告4
- extern C C 调用c++
- 工欲善其事,必先利其器-程序员工具推荐
- 【5】天猫精灵开放平台实验—基于天气查询模板创建开发屏显页面技能
- CentOS6实验模板机搭建
- 计算机网络协议测试技术分析
- [转载]尺度函数与小波函数
- arachni_web显示500,We‘re sorry, but something went wrong.
- esxi突然启动不起来了!显示:Error loading /sb.v00
- 来自CCNet的一种创新:语义分割中的十字交叉视觉注意力
- LCA——JD 3055 Nearest Common Ancestors