Description

Marah要出去买菜,但不小心迷路了,它记得所有菜店的坐标,也知道它现在的坐标。请你帮帮她,找 到一条买完菜的路吧。它已经急得快哭了,它想要买完菜回家。因此它需要你找到一条最短的路买菜。
她穿上了最新研发的机甲,这个机甲的体格能够变化, 为了使自己尽量炫酷,她因此它希望在路径最短 的情况下使自己的体格最大,即在移动时离障碍尽可能远。因为你开着上帝视角,所以你知道小T所在 的地图。你能帮它找到一条路吗?
注意: 1、此处的离障碍最远是保证在任何时候、在保证路径最短的情况下离障碍最远。当然小T只需 要你保证 在每个位置的体格之和尽可能大。 2、不需要考虑小T回家的路。

Input Format

第一行两个数 ,表示小T所在的地图大小和小T的最大体格。 体格为 表示小T会占据 ( 2 i + 1 ) ∗ ( 2 i + 1 ) (2i+1)*(2i+1) (2i+1)∗(2i+1) 个格子。 接下来 行每行 个数字表示地图,其中‘1’表示障碍,'0’表示空地。 接下来一行三个数 x , y , p x,y,p x,y,p表示小T所在的坐标 ( x , y ) (x,y) (x,y)和菜店数量 p p p。 接下来 p p p 行,第 两个数表示菜店 i i i所在 的坐标。

Output Format

输出两个数,表示最短路长度以及每个位置的体格之和。

Constraints

对于 20%的数据,所有菜市位置和小T所在的位置在一条水平直线上。 对于另外 30%的数据, s = 0 s=0 s=0 ,其中 20%的数据还满足 n , m ≤ 50 n,m\le50 n,m≤50
对于另外20% 的数据, p = 1 p=1 p=1
对于100%的数据, n , m ≤ 300 , s ≤ 10 , p ≤ 15 n,m\le300,s\le10,p\le15 n,m≤300,s≤10,p≤15

题解

先来考虑部分分的做法:
1.当体格系数为0时,不用考虑小T会膨胀,转变成了旅行商问题,预处理出两两菜市场之间的距离,鉴于是网格图,p遍bfs就可以处理出。 用 f [ i ] [ j ] f[i][j] f[i][j]表示目前在i点,走过的菜市场状态为二进制数j点,状压DP经典。

2.当只有一个菜市场时,只需要考虑小T能否膨胀,预处理出每一个点可以膨胀的最大限度,在bfs中直接比较即可。

Full marks —( B y − M r W u By -Mr Wu By−MrWu)
将上述两种算法结合在一起即可。

第一步

设 d i s [ n u m ] [ i ] [ j ] dis[num][i][j] dis[num][i][j]表示第 n u m num num个菜市场到点 ( i , j ) (i,j) (i,j)的最短距离, v a l [ n u m ] [ i ] [ j ] val[num][i][j] val[num][i][j]表示第num个菜市场到点 ( x , y ) (x,y) (x,y)的最大膨胀和【包括菜市场】

对于每一个菜市场,bfs的同时先以最短距离为第一关键字,最大膨胀和为第二关键字,即最短距离被更新的时候要放弃当前的最大膨胀和,变成更新它的状态的最大膨胀和,当一个点 x x x访问到另一个已经访问过的点 y y y,若到 y y y的最短距离也可以由到 x x x的距离+1来得到,那么说明 y y y在 x x x当前的最短路上,那么就可以用到 x x x的最大膨胀和来更新到 y y y的最大膨胀和。(双关键字bfs)

第二步

f [ i ] [ j ] [ 0 ] f[i][j][0] f[i][j][0]表示目前走过菜市场的状态为 j j j,目前在 i i i点的最短距离
f [ i ] [ j ] [ 1 ] f[i][j][1] f[i][j][1]表示目前走过菜市场的状态为 j j j,目前在 i i i点,在当前最短路下的最大可膨胀度。

此时状压DP更新也是双关键字,类似于bfs更新操作,先比较距离,距离相同在比较最大膨胀即可。
【注意】:更新最大膨胀度的时候需要减去重复计算的菜市场的贡献。

第三步

从最短距离的状态中选出最大膨胀度的状态。
边枚举边比较即可。

Code

#include<bits/stdc++.h>
#define ll long long
#define rint register int
using namespace std;
const int dx[4]={0,1,0,-1};
const int dy[4]={1,0,-1,0};
inline int read()
{int s=0,f=1;char ch;for(;ch<'0' || ch>'9';ch=getchar())   if(ch=='-') f=1;for(;ch>='0' && ch<='9';ch=getchar()) s=(s<<1)+(s<<3)+ch-'0';return s*f;
}
struct node{int x,y;};
int n,m,s,a[305][305],sum[305][305],w[305][305],f[21][(1<<15)+100][2];
int dis[21][305][305],val[21][305][305],vis[305][305],w1,w2,p,ans1,ans2;
/*dis[i][j][k]表示第i个菜市场到点(x,y)的最短距离,val[i][j][k]表示第i个菜市场到点(x,y)最大可膨胀值f[i][j][0]表示目前走过菜市场的状态为j,目前在i点的最短距离f[i][j][1]表示目前走过菜市场的状态为j,目前在i点,在当前最短路下的最大可膨胀度
*/
inline int ask(int x1,int y1,int x2,int y2)
{return sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1];
}
void check(int x,int y)//计算出每一个点的可膨胀度
{for(int k=s;k>=0;k--){if(x-k<1||x+k>n||y-k<1||y+k>m) continue;if(ask(x-k,y-k,x+k,y+k)==0){ w[x][y]=k; return;}}return;
}
void BFS(int num,int sx,int sy)
{queue<node> q;while(q.size()) q.pop();q.push(node{sx,sy});dis[num][sx][sy]=0; val[num][sx][sy]=w[sx][sy];memset(vis,0,sizeof(vis)); vis[sx][sy]=1;while(q.size()){node tmp=q.front();int x=tmp.x,y=tmp.y; q.pop();for(int i=0;i<4;i++){int xx=x+dx[i];int yy=y+dy[i];if(xx<1||yy<1||xx>n||yy>m) continue;if(a[xx][yy]) continue;if(!vis[xx][yy]){vis[xx][yy]=1;dis[num][xx][yy]=dis[num][x][y]+1;val[num][xx][yy]=val[num][x][y]+w[xx][yy];q.push(node{xx,yy});}else{if(dis[num][xx][yy]==dis[num][x][y]+1)//xx,yy已经被访问到,它在x,y的最短路上---可以被更新 val[num][xx][yy]=max(val[num][xx][yy],val[num][x][y]+w[xx][yy]);}}}
}
int main()
{freopen("expand.in","r",stdin);freopen("expand.out","w",stdout);n=read(); m=read(); s=read();for(rint i=1;i<=n;i++)for(rint j=1;j<=m;j++)a[i][j]=read();for(rint i=1;i<=n;i++)for(rint j=1;j<=m;j++)sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];for(rint i=1;i<=n;i++)for(rint j=1;j<=m;j++){ if(a[i][j]==1) {w[i][j]=-999;continue;}check(i,j);}for(rint i=1;i<=p;i++)for(rint j=1;j<=n;j++)for(rint z=1;z<=m;z++)dis[i][j][z]=1e9,val[i][j][z]=-1e9;w1=read(),w2=read(),w1++,w2++;//起点 p=read();node b[21];for(rint i=1;i<=p;i++){b[i].x=read(); b[i].y=read();b[i].x++; b[i].y++;BFS(i,b[i].x,b[i].y);}for(int i=0;i<(1<<p);i++)for(int j=0;j<=p;j++)f[j][i][0]=1e9,f[j][i][1]=-1e9;for(int i=1;i<=p;i++)//初值f[i][1<<(i-1)][0]=dis[i][w1][w2],f[i][1<<(i-1)][1]=val[i][w1][w2];for(int i=1;i<(1<<p);i++)for(int j=1;j<=p;j++)if(i&(1<<(j-1)))//j是目前所在的菜市场{for(int z=1;z<=p;z++)//前往下一个没去过菜市场if(!(i&(1<<(z-1)))){if(f[j][i][0]+dis[j][b[z].x][b[z].y]<f[z][i|(1<<(z-1))][0])//最短路被更新,最大膨胀度要改变f[z][i|(1<<(z-1))][0]=f[j][i][0]+dis[j][b[z].x][b[z].y],f[z][i|(1<<(z-1))][1]=f[j][i][1]+val[j][b[z].x][b[z].y]-w[b[j].x][b[j].y];if(f[j][i][0]+dis[j][b[z].x][b[z].y]==f[z][i|(1<<(z-1))][0])//最短路相同,更新最大膨胀度                                                                                  f[z][i|(1<<(z-1))][1]=max(f[z][i|(1<<(z-1))][1],f[j][i][1]+val[j][b[z].x][b[z].y]-w[b[j].x][b[j].y]);//减去重复计算的j菜市场的贡献}}ans1=1e9,ans2=-1e9;for(int i=1;i<=p;i++){ if(f[i][(1<<p)-1][0]<ans1) ans2=f[i][(1<<p)-1][1],ans1=f[i][(1<<p)-1][0];if(f[i][(1<<p)-1][0]==ans1) ans2=max(ans2,f[i][(1<<p)-1][1]);}printf("%d %d",ans1,ans2);
}

【NOIP模拟赛】迷路 expand 题解相关推荐

  1. NOIP 模拟赛 长寿花 题解

    NOIP 模拟赛 长寿花 题解 要放 \(n\) 层物品,第 \(i\) 层有 \(a_i\) 个位置放物品,物品有 \(m\) 中颜色,有约束条件: 同一层两个相邻物品颜色不能相同. 相邻两层颜色集 ...

  2. NOI.AC NOIP模拟赛 第六场 游记

    NOI.AC NOIP模拟赛 第六场 游记 queen 题目大意: 在一个\(n\times n(n\le10^5)\)的棋盘上,放有\(m(m\le10^5)\)个皇后,其中每一个皇后都可以向上.下 ...

  3. 【noip模拟赛4】Matrix67的派对 暴力dfs

    [noip模拟赛4]Matrix67的派对 描述 Matrix67发现身高接近的人似乎更合得来.Matrix67举办的派对共有N(1<=N<=10)个人参加,Matrix67需要把他们安排 ...

  4. 【HHHOJ】NOIP模拟赛 捌 解题报告

    点此进入比赛 得分: \(30+30+70=130\)(弱爆了) 排名: \(Rank\ 22\) \(Rating\):\(-31\) \(T1\):[HHHOJ260]「NOIP模拟赛 捌」Dig ...

  5. NOIP模拟赛 17.10.10

    初次见面(firstmeet) [题目背景] 雾之湖边,静得可怕. 露米娅出神凝望.黑白连衣裙,像极了绽放的墨黑和洁白的莲.身边的雾之 湖,倒映着血色天空.酒红的双眸,映照一切.低声浅笑,双臂伸直,她 ...

  6. jyzy noip模拟赛5.22-2

    不知道哪来的题 jyzy noip模拟赛5.22-2 样例输入 1 2 3 4 样例输出 0.200000000000000 数据 |a|,|b|,|c|,|d|<=1e9 很多大佬迅速想到二分 ...

  7. 第十四届蓝桥杯第一期模拟赛试题与题解 C++

    第十四届蓝桥杯第一期模拟赛试题与题解 C++ 试题 A 题解:位运算 试题 B 题解:日历模拟 试题 C 题解:double 求和 试题 D 题解:枚举 试题 E 题解:二维前缀和 试题 F 题解:两 ...

  8. NOIP模拟赛csy2021/10/30

    NOIP模拟赛csy2021/10/30 比赛时间规划 赛后反思与总结 这..总的来说感觉打的很不好,根本没有状态,有一部分原因是今天来晚了,太慌,更多的还是这次题感觉很难o(╥﹏╥)o 比赛时间规划 ...

  9. 【WZOI第二次NOIP模拟赛Day1T2】世界末日 解题报告

    [WZOI第二次NOIP模拟赛Day1T2]世界末日 Problem 2 世界末日 (doomsday.pas/c/cpp) 背景 话说CWQ大牛终于打开了那扇神秘大门,但迎接他的不是什么神秘的东西, ...

  10. 辣鸡(ljh) NOIP模拟赛 模拟 平面几何 数论 化学相关(雾)

    [题目描述] 辣鸡ljhNOI之后就退役了,然后就滚去学文化课了. 然而在上化学课的时候,数学和化学都不好的ljh却被一道简单题难住了,受到了大佬的嘲笑. 题目描述是这样的:在一个二维平面上有一层水分 ...

最新文章

  1. 基本CSS选择器,复合选择器,后代选择器
  2. java导出csv文件使用Excel打开乱码问题
  3. 线性代数学习笔记(几何版)
  4. 『软件工程4』一文了解软件项目管理中的4P
  5. Pycharm安装第三方库
  6. shiro学习(20): 自定义过滤规则
  7. Java Integer类highestOneBit()方法与示例
  8. 泊松分布的理解与Python仿真
  9. 如何获得getElementById的length这个数值?
  10. asp.net读写XML小结
  11. 初学Rman 写的备份脚本
  12. 《乌合之众》思维导图
  13. snakeyaml java_JAVA使用SnakeYAML解析与序列化YAML
  14. Ubuntu安装OpenRasp后台管理
  15. Windows远程连接Linux界面的两种方法
  16. 新浪vip邮箱 服务器,新浪手机邮箱
  17. 第二篇:呈现内容_第三节:CompositeControl呈现
  18. 人间哪知星空遥:荣耀30系列的巡天计划
  19. 旧机还在换盆?! Linux deploy让她再发光!
  20. 巧用Excel笔画排序,实现计算汉字笔画数

热门文章

  1. IPhone手机页面中点击输入框,弹出键盘网页会放大的解决方法
  2. 【面经】FaceBook
  3. 遗传算法在离散型工厂选址问题中的应用
  4. AdaBoost 算法
  5. C语言sort函数如何使用
  6. python123照猫画虎求阶乘_单片机 - 21ic中国电子网
  7. 【Linux】制作Linux系统(Ubuntu)U盘启动盘(含UltraISO安装及注册码)
  8. 李飞飞高徒 Andrej Karpathy:计算机科学博士的生存指南
  9. 【题解】P2921 在农场万圣节(tarjan)
  10. 电脑耳机为什么会有很大噪声