【COCI】 2271 邮递员 暴力(不是树形DP)题解 c++
来源:互联网 发布:数据库的事务是什么 编辑:程序博客网 时间:2024/06/14 22:59
【COCI】邮递员 2271
题目描述
Mirko在一个山镇找到了一份邮递员的工作。这个镇可以看作一个N*N的矩形。每个区域可能是以下之一:房子K,邮政局P,草地 ‘.’。每个区域都有一个海拔。
每天早上,Mirko要送信给镇上所有的家庭。他从邮局P处开始,可以向8个方向到相邻的一个区域,当他送完最后一份信后,他必须回到邮局。
现在用Mirko走过的路线中海拔最高点和最低点之差来表示他的疲劳程度。帮他计算出送出所有的信最少的疲劳值。
输入
第一行包含整数N(2<=N<=50)。接下来的N行表示矩形。P只出现一次,而K最少出现一次。
接下来N行每行包含N个正整数,表示相应区域的海拔。均小于1000000.
输出
单独的一行,一个整数,表示最小的疲劳值。
样例输入
2
P.
.K
2 1
3 2
样例输出
0
分析: 每个点都有一个海拔,而要我们求符合要求的路线中,海拔值最高与最低的值的差最小。根据经验,大部分求最大-最小的题都是通过二分差值来AC的。于是马上得出一个复杂度略(很)高的解法:
1. 二分最大-最小
2. 枚举最小,算出最大
3. dfs||bfs, 验证算出的范围是否能让mirko完成任务(将范围外的点删去)
4. 输出答案
估算时间复杂度:
(log 1e6) //二分
* 1e6 //枚举下界
* 50*50//dfs||bfs
有点大
优化一: 海拔值只有2500种,意味着我们只需要枚举下界2500次,即离散化。有多种方式,但为了简单并且方便,我推荐用STL的set||sort,高效又好写。
复杂度变为:20(log 1e6)* 2500 *2500 = 125000000(明显超时)
优化二:由于房子你必须经过,所以枚举下界和上界时下界小于等于房子的最小值,上界大于等于房子的最大值;(最强力的剪枝,直接快了1s左右)优化三:其实这个有点卡数据,dfs和bfs使用时枚举方向的数组顺序要找好,大家可以试试不同的顺序,也许就AC了呢,楼主就靠这个把时间从1000打到了985,好不容易AC(见代码)。优化四:dfs时判断点能不能走,用vis,在函数外预处理,反正楼主靠此搞了300ms回来。贴AC代码:985ms
#include<cstdio>#include<cstring>#include<set>#include<queue>#include<algorithm>#define maxn 55#define F first#define S secondusing namespace std;set<int>s;int n,dis[maxn][maxn],cnt_k;char map[maxn][maxn];pair<int,int>b,now,k[2505];int U[8]={-1,-1,-1,0,0,1,1,1},z[8]={-1,0,1,-1,1,-1,0,1};bool vis[maxn][maxn];bool check(int u,int v){ return u>0&&u<=n&&v>0&&v<=n&& !vis[u][v];}void get(int &res) { res=0; int flag=1;char c; while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1; while(c>='0'&&c<='9')res=res*10+c-48,c=getchar(); res*=flag; } void dfs(int x,int y){ int u,v; for(int i=0;i<8;i++) if(check(u=x+U[i],v=y+z[i])) { vis[u][v]=1; dfs(u,v); }}bool search(int head,int tail){ memset(vis,-1,sizeof vis); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(dis[i][j]>=head&&dis[i][j]<=tail) vis[i][j]=0; dfs(b.F,b.S); for(int i=0;i<cnt_k;i++) if(vis[k[i].F][k[i].S]!=1) return 0; return 1;}int main(){ int maxh,minh,_minh=2e9,_maxh=0; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%s",map[i]+1); for(int j=1;j<=n;j++){ if(map[i][j]=='P') b=make_pair(i,j); if(map[i][j]=='K') k[cnt_k++]=make_pair(i,j); } } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ get(dis[i][j]); s.insert(dis[i][j]); } _minh=min(_minh,dis[b.F][b.S]); _maxh=max(_maxh,dis[b.F][b.S]); for(int i=0;i<cnt_k;i++){ _minh=min(_minh,dis[k[i].F][k[i].S]); _maxh=max(_maxh,dis[k[i].F][k[i].S]); } set<int>::iterator it=s.end(); it--; maxh=*it; minh=*s.begin(); int l=_maxh-_minh,r=*(it)-*(s.begin()),mid; while(l<r){ bool flag=0; mid=(l+r)>>1; for(it=s.begin();it!=s.end();it++) { if(*it>_minh || *it+mid<_maxh) continue; if(search(*it,*it+mid)) { flag=1; break; } } if(!flag) l=mid+1; else r=mid; } printf("%d",l);}
- 【COCI】 2271 邮递员 暴力(不是树形DP)题解 c++
- 毯子 题解(COCI 2008-2009Final C)
- #COCI#玻璃杯(状压DP)
- 邮递员送信(luogu 1629)题解
- [题解] P2015 二叉苹果树(树形DP)
- [题解] P2014 选课(树形DP+拓扑)
- COCI 2016/2017 Round 4 C dp
- 暴力大神hxx 树形dp
- 【HNOI2004】邮递员 (插头DP一条回路)
- 【模拟】【暴力】[COCI]排序
- 【题解】 树形dp 守卫部署
- Vijos P1110 小胖邮递员(HNOI2004)题解
- 树形DP图画入门题解2 (HDU2196)
- hdu 5469 Antonidas 树形dp+暴力 ★
- [树形DP 暴力] BZOJ 3696 化合物
- 【COCI 2015/2016 #7】PROZOR(加强版) 题解
- ASC(1)C(树形DP)
- Codeforces 708C Centroids(树形dp)
- 陀螺仪背景图效果
- 【OpenCV入门指南】第十篇 彩色直方图均衡化
- HDU 2955 Robberies(01背包)
- 设计模式讲解与代码实践(十)——装饰
- LightOJ 1422 (区间DP)
- 【COCI】 2271 邮递员 暴力(不是树形DP)题解 c++
- 机器学习(十一)- Multiclass Classification
- Prometheus采集用的exporter
- 单链表的实现
- Android数据存储与共享
- 【设计模式】常见设计模式
- c/c++整理--私有继承
- (一)MATSim安装教程
- PHP安全的URL字符串base64编码和解码