晚上十点十分才a了这题,太难了。

Description

探险者拉罗最近发现了一个远古的宫殿,该宫殿可以表示为N×N个格子的迷宫,其中有一个格子是入口(用E表示),一个格子是出口(用X表示),有若干个格子是藏金点(用G表示),有若干个格子是障碍物(用#表示),其他格子都有怪物在里面(用-表示)。拉罗由入口开始探险,希望到达尽量多的藏金点,然后由出口离开。当然,障碍物是不能通过的。而且,由于那些远古的怪物异常凶狠,一旦被它们发现,拉罗必死无疑。幸运的是,经过多年的磨练,拉罗练就了一身非凡的本领,其中有一招叫做潜行,当她使用潜行经过有怪物的格子时,怪物是不会发现她的。不幸的是,她不能连续潜行太久,不然就会窒息,准确来说,她最多可以连续潜行着经过M个有怪物的格子。现在拉罗手头上已经有整个迷宫的地图,她需要规划出一条完整的行动路线,希望访问到尽量多的藏金点,在保证访问最多个藏金点的基础上,她还希望潜行的总时间最少(走一格为1个单位时间)。你可以帮助她吗?
  注意,每个格子都可以多次被访问,同一个怪物格子每访问一次潜行总时间就加1,但同一个藏金点无论被访问多少次都只能算作一个,另外,即使走到了出口她也可以选择先不出去而继续走到其他点。数据保证拉罗可以由出口离开。

Input

输入第一行是两个整数N(1 <= N <= 100)和M(1 <= M <= 200),分别表示迷宫的边长和拉罗最多可以连续潜行的格子数。
  接下来N行每行一个字符串,每个字符串恰好有N个字符,字符串仅包含’E’、’X’、’G’、’#’、’-’。保证有且仅有一个E,有且仅有一个X,不超过16个G。

Output

输出一行,包含两个整数,分别是可以访问到的最多的藏金点数和在访问最多藏金点的基础上所需的最少的潜行总时间,两个整数之间用一个空格隔开。

Sample Input

3 1
E-G
#G-
–X

Sample Output

2 3

Hint

【数据范围】
  对于50%的数据,藏金点G不超过8个。

赛时

一看金子<=16,就知道是我不会的状压dp

正解

实际上就是状压dp

我们先将起点,终点,和金子压到所谓的二进制中。那么1代表这个点到过,0则代表没到过。这三者加一起才18,所以完全装得下。

f[s][i]表示s这个状态下到i时的最小潜行时间,那么方程即是:f[s’][j]=min(f[s’][j],f[s][i]+dis[i][j]);(s’代表更新的一个状态,dis是求每每(起点,终点,和金子)之间的最短距离)

可能还会不懂,没事,一步步来

首先我们将起点,终点和金子之间的最小距离用bfs求出来。

代码

void bfs(int x,int y){memset(vis,0,sizeof(vis));//是否访问过memset(d,0,sizeof(d));//数组模拟队列t=1;h=0;//头与尾d[t][0]=x,d[t][1]=y,d[t][2]=0,d[t][3]=0;//初值,0为坐标x,1为坐标y,2为当前潜行时间,3为一共潜行时间vis[x][y]=1;//起点访问过while(h++<t){for(int i=0;i<4;i++){nx=d[h][0]+xx[i];ny=d[h][1]+yy[i];//新坐标if(nx<1||nx>n||ny<1||ny>n||vis[nx][ny]||bz[nx][ny]==3)continue;//边界,我设bz数组为x,y位置的情况,1为起点和终点,2为//金子,3为障碍物,0为怪兽if(bz[nx][ny]==1||bz[nx][ny]==2){//若是起点,终点,或金子now=0,sum=d[h][3];//now为当前潜行时间,这时为0//sum为当前总时间,不变dis[num[x][y]][num[nx][ny]]=dis[num[nx][ny]][num[x][y]]=min(dis[num[x][y]][num[nx][ny]],sum);//num来存起点,终点,或金子是第几个,这里遇到个三个玩意之一//更新一下最短路径}else if(d[h][2]+1>m)continue;//潜行时间超标else now=d[h][2]+1,sum=d[h][3]+1;//在怪兽上,当前,总和都加1vis[nx][ny]=1;//访问过d[++t][0]=nx,d[t][1]=ny,d[t][2]=now,d[t][3]=sum;//入队}}
}

之后dp

void dp(){memset(f,127,sizeof(f));f[1][0]=0;//起点初值为0for(int state=1;state<=(1<<tot+1)-1;state++){//state为状态int sta=state;while(sta) cnt[state]+=sta&1,sta>>=1;//sta来判断有多少个1for(int i=0;i<=tot;i++)//枚举i,从i走到jif(state&(1<<i)&&f[state][i]!=inf){//状态里包含i,并且不是inf,这个一个优化for(int j=0;j<=tot;j++)if(i!=j)//枚举j,从i走到j,所以不能相等f[state|(1<<j)][j]=min(f[state|(1<<j)][j],f[state][i]+dis[i][j]);//state|(1<<j)意为state//这个状态再更新成含有j的,即在二进制下第j位为0}}
}

随后找要求的两个值

 ans1=-inf;ans2=inf;//ans1为藏金数,ans2为最小的潜行时间for(int state=1;state<=(1<<tot+1)-1;state++)//状态if(state&1&&state&(1<<tot)){//包含起点与终点才符题意int sta=state-1-(1<<tot);//除去起点与终点if(cnt[sta]>ans1) ans1=cnt[sta],ans2=f[state][tot];else if(cnt[sta]==ans1) ans2=min(ans2,f[state][tot]);//更新ans1,ans2}printf("%d %d",ans1,ans2);

然后发一下总代码

#include<cstdio>
#include<iostream>
#include<cstring>
#define inf 0x7f7f7f7f
using namespace std;int stx,sty,ndx,ndy;
int n,m,t,h,ans1,ans2,nx,ny,now,sum,tot;
int bz[107][107],num[107][107],cnt[(1<<18)+10],f[(1<<18)+10][20],d[20007][4],dis[20][20];
int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0};
bool vis[107][107];
char s[107];void bfs(int x,int y){memset(vis,0,sizeof(vis));memset(d,0,sizeof(d));t=1;h=0;d[t][0]=x,d[t][1]=y,d[t][2]=0,d[t][3]=0;vis[x][y]=1;while(h++<t){for(int i=0;i<4;i++){nx=d[h][0]+xx[i];ny=d[h][1]+yy[i];if(nx<1||nx>n||ny<1||ny>n||vis[nx][ny]||bz[nx][ny]==3)continue;if(bz[nx][ny]==1||bz[nx][ny]==2){now=0,sum=d[h][3];dis[num[x][y]][num[nx][ny]]=dis[num[nx][ny]][num[x][y]]=min(dis[num[x][y]][num[nx][ny]],sum);}else if(d[h][2]+1>m)continue;else now=d[h][2]+1,sum=d[h][3]+1;vis[nx][ny]=1;d[++t][0]=nx,d[t][1]=ny,d[t][2]=now,d[t][3]=sum;}}
}void dp(){memset(f,127,sizeof(f));f[1][0]=0;for(int state=1;state<=(1<<tot+1)-1;state++){int sta=state;while(sta) cnt[state]+=sta&1,sta>>=1;for(int i=0;i<=tot;i++)if(state&(1<<i)&&f[state][i]!=inf){for(int j=0;j<=tot;j++)if(i!=j)f[state|(1<<j)][j]=min(f[state|(1<<j)][j],f[state][i]+dis[i][j]);}}
}int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%s",s+1);for(int j=1;j<=n;j++){if(s[j]=='E')stx=i,sty=j,bz[i][j]=1;if(s[j]=='X')ndx=i,ndy=j,bz[i][j]=1;if(s[j]=='G')bz[i][j]=2,num[i][j]=++tot;if(s[j]=='#')bz[i][j]=3;}}num[stx][sty]=0;num[ndx][ndy]=++tot;memset(dis,127,sizeof(dis));for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(bz[i][j]==1||bz[i][j]==2)bfs(i,j);dp();ans1=-inf;ans2=inf;for(int state=1;state<=(1<<tot+1)-1;state++)if(state&1&&state&(1<<tot)){int sta=state-1-(1<<tot);if(cnt[sta]>ans1) ans1=cnt[sta],ans2=f[state][tot];else if(cnt[sta]==ans1) ans2=min(ans2,f[state][tot]);}printf("%d %d",ans1,ans2);
}

2020.01.18【NOIP提高组】模拟B 组——总结——探险者拉罗相关推荐

  1. JZOJ 5281. 【NOIP提高组模拟A组8.15】钦点

    Description Input Output Sample Input 4 4 2 a a b b a a b b c c d d c c d d 1 1 3 3 2 2 3 1 1 3 2 2 ...

  2. JZOJ5857 【NOIP提高组模拟A组2018.9.8】没有上司的舞会

    题目 Description "那么真的有果尔德施坦因这样一个人?"他问道. "是啊,有这样一个人,他还活着.至于在哪里,我就不知道了." "那么那个 ...

  3. 2020牛客NOIP赛前集训营-普及组第三场C牛半仙的妹子树

    链接:https://ac.nowcoder.com/acm/contest/7608/C 来源:牛客网 牛半仙有 n​ 个妹子,她们所在的位置组成一棵树,相邻两个妹子的距离为 1​. 有 m​ 个妹 ...

  4. Robcup2D足球学习记录【2020.01.18】

    本次主要学习了bhv_attackers_move.cpp和bhv_strict_check_shoot.cpp bhv_strict_check_shoot.cpp 代码个人理解与存在的问题(已经通 ...

  5. 【二分,找规律】Day 14 提高组模拟C组 T1 小麦亩产一千八

    题目大意 给定斐波那契的第aaa项,求出第b" role="presentation">bbb项,默认第0项为1 解题思路 方法一:递推 找到规律后O(b)O(b) ...

  6. 纪中集训2020.01.13【NOIP普及组】模拟赛C组总结————My First Time Write Summary

    纪中集训2020.01.13[NOIP普及组]模拟赛C组总结 题目编号 标题 0 [NOIP普及组模拟]取值( numbers.pas/cpp) 1 [NOIP普及组模拟]数对(pairs.pas/c ...

  7. 2021.01.14【NOIP提高B组】模拟 总结

    2021.01.14[NOIP提高B组]模拟 总结 第一题 Candy 奇奇怪怪的题目. 一开始没有理解题目,其实就是同时变换. 打了一个暴力. 本人随机生成50000组数据,都过了,时间没超.希望出 ...

  8. 纪中集训2020.01.16【NOIP普及组】模拟赛C组总结+【0.Matrix】分析

    纪中集训2020.01.16[NOIP普及组]模拟赛C组总结+[0.Matrix]分析 题目: 0.matrix 1.product 2.binary 3.value 巨佬估分:100+100+40+ ...

  9. 2020.08.08【NOIP提高组】模拟:奶牛的图片 总结

    2020.08.08[NOIP提高组]模拟:奶牛的图片 总结 Description Farmer John希望给他的 N ( 1 ≤ N ≤ 100 , 000 ) N(1\leq N\leq100 ...

  10. 第一届『Citric杯』NOIP提高组模拟赛 题解

    [官方题解]第一届『Citric杯』NOIP提高组模拟赛 题解 第一题 柠檬超市 这题是本次模拟赛的送分题.做法显然. 但是注意此题有一个陷阱: 注意W和C的规模都是10^9,所以如果直接用doubl ...

最新文章

  1. 17福师《计算机应用基础,17春福师《计算机应用基础》在线作业一.doc
  2. 《构建高可用Linux服务器》卓越网和互动网上架了
  3. delphi 安卓图片保存数据库_delphi 把图片存入数据库
  4. 除阿里、网易和字节外,杭州居然还有这么多互联网公司!
  5. 深入理解ArrayList
  6. C/C++网络编程工作笔记0001---网络编程的基本概念
  7. SharePoint 2010新特性文档集
  8. 在Windows 10 环境下安装 Hadoop-3.1.2
  9. html快闪软件制作,抖音如何制作快闪视频?怎样快速制作炫酷视频?
  10. Java和Python哪个更适合初学者的问题
  11. 方舟开服务器游戏基础管理设置
  12. sql if语句实例
  13. 医学图像分类_深度学习与医学图像分析
  14. 确定目标 目标确定的七大原则
  15. 将iGoogle-Style新标签页添加到Chrome
  16. asp.net报表制作视频教程
  17. PHP小马免杀的浅谈[过最新D盾]
  18. 我是K哥,大厂高管,抓住过几次风口,交个朋友吧
  19. 通过左旋和右旋来实现搜索二叉树的自平衡
  20. 主成分回归python实现

热门文章

  1. 趣味Python — 不到20行代码制作一个 “手绘风” 视频
  2. 树莓派PI2编译天猫魔盘驱动,附编译好ko文件
  3. 小程序组件库ColorUI教程
  4. 美国 GLOBAL DOSSIER全球专利案卷系统使用方法,有图说明
  5. 《完全写作指南》读书笔记
  6. exoplay切换全屏_ExoPlayer播放视频的简单使用及播放视频宽高设置的源码分析
  7. war压缩命令_宝塔面板linux版解压WAR文件时,如何解压的三种方法介绍
  8. js获取当前服务器信息,js获取当前URL、参数、端口、IP等服务器信息
  9. 收费最低的云存储_营业收费系统|自来水管理系统|自来水公司收费管理系统|手机移动抄表|网上营业厅|短信服务平台...
  10. itools苹果录屏大师_屏幕录制软件有哪些?找对合适录屏软件