题目链接: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相关推荐

  1. 计蒜客模拟赛D1T3 蒜头君的坐骑:用dfs转移dp

    题目链接:https://nanti.jisuanke.com/t/16447 题意: 蒜头君有一只坐骑,人马. 一天,蒜头君骑着他的坐骑走上了一片n*m的大荒野,一开始时,蒜头君在(1,1)点,他要 ...

  2. 2020蓝桥杯B 组省赛计蒜客模拟赛(一)题解

    2020蓝桥杯省赛 B 组计蒜客模拟赛(一)目录 试题 A:有趣的数字(结果填空) 试题 B:爬楼梯(结果填空) 试题 C:七巧板(结果填空) 试题 D:苹果(结果填空) 试题 E:方阵(结果填空) ...

  3. 【计蒜客模拟赛系列】-计蒜客2021年8月普及组模拟赛

    提前:本文中部分代码和思路有借鉴或摘抄计蒜客官方题解 赛后总结 本次模拟赛的难度总算正常了些 个人战绩: 220/400,排名61 ,太弱了,一大堆AK爷 题目质量评价: 题目相比CSP-J还是简单了 ...

  4. 计蒜客模拟赛5-礼物盒

    小y 有一个宽度为 100cm,高度为 20cm,深度为 1cm 的柜子,如下图. 小y 还有 36个礼物盒,他们的深度都为 1cm. 他们对应的宽度和高度如下,单位(cm). 11 3 8 12 1 ...

  5. 计蒜客模拟赛7礼品盒

    第七题 小y 有一个宽度为 100cm,高度为 20cm,深度为 1cm 的柜子,如下图. 小y 还有 3636 个礼物盒,他们的深度都为 1cm. 他们对应的宽度和高度如下,单位(cm). 现在小y ...

  6. 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 ...

  7. 糖果(2019第十届蓝桥杯省赛C++A组I题) 解题报告(状压dp) Apare_xzc

    糖果(2019第十届蓝桥杯省赛C++A组I题) 解题报告(状压dp) xzc 2019/4/5 试题 I: 糖果 时间限制: 1.0s 内存限制: 256.0MB 本题总分:25分 [问题描述]    ...

  8. 牛客网 小白月赛4 D-郊区春游 最短路+状压dp

    链接: https://www.nowcoder.com/acm/contest/134/D来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524 ...

  9. Nise-Anti-AK Problem 计蒜客网络赛

    水题 Description: Peppa has been learning math recently, he is trapped by a easy problem. He is given ...

  10. 【计蒜客 - 蓝桥训练】修建公路(贪心,或运算,dp)

    题干: 蒜头国有 nn 座城市,编号分别为 0,1,2,3,\ldots,n-10,1,2,3,-,n−1.编号为 xx 和 yy 的两座城市之间如果要修高速公路,必须花费 x|yx∣y 个金币,其中 ...

最新文章

  1. HTTP的KeepAlive是开启还是关闭?
  2. Educational Codeforces Round 2 B. Queries about less or equal elements
  3. linux cpu占用100原因查询,如何根据查询异常时间节点和连接进而确定CPU使用率100%的原因...
  4. android手势识别
  5. WIN10的IE错误代码inet_e_resource_not_found解决办法
  6. 平行四边形的特殊性质
  7. 小程序 | 云函数获取用户openid
  8. (138)System Verilog覆盖率目标设置
  9. python安装mysqldb模块_python MysqlDb模块安装及其使用详解
  10. java实验报告2013_java实验报告4
  11. extern C C 调用c++
  12. 工欲善其事,必先利其器-程序员工具推荐
  13. 【5】天猫精灵开放平台实验—基于天气查询模板创建开发屏显页面技能
  14. CentOS6实验模板机搭建
  15. 计算机网络协议测试技术分析
  16. [转载]尺度函数与小波函数
  17. arachni_web显示500,We‘re sorry, but something went wrong.
  18. esxi突然启动不起来了!显示:Error loading /sb.v00
  19. 来自CCNet的一种创新:语义分割中的十字交叉视觉注意力
  20. LCA——JD 3055 Nearest Common Ancestors

热门文章

  1. 详解分布式系统与消息投递(架构师必备)
  2. 别了 Java EE!开源组织将其更名为Jakarta
  3. 想要转人工智能,程序员该如何学习?
  4. Facebook是如何支持80万并发视频流直播的?
  5. 代码重构方向原则指导
  6. 推荐一些学习方面的公众号
  7. bp算法中为什么会产生梯度消失?
  8. 百度地图之添加控件——比例尺、缩略图、平移缩放
  9. UIKit框架-基础控件Swift版本: 7.UISwitch方法/属性详解
  10. [19/06/08-星期六] CSS基础_表格表单