设船最宽行列的交点为船的重心,那么只要预处理出重心在每个位置是否可行,以及在边界上走出边界所需的最小值之后,进行一遍BFS即可。

枚举每个点$(x,y)$,求出它上下最近的障碍物的距离。考虑重心在第$x$行左右移动的时候,不能走的部分是一个区间,可以$O(1)$计算。

对于左右障碍物也同理,因此可以通过维护差分前缀和可以做到$O(n^2)$预处理出所有可行位置。

对于边界,首先一定可以通过一直往一个方向走得到一个解;其次对于四个角落上的点,可以通过$O(n)$枚举它卡住船的哪个角落来得到走出地图的最优解。

总时间复杂度为$O(n^2)$。

#include<cstdio>
const int N=2010,inf=100000000;
int n,i,j,x,y,z,xl=inf,xr,yl=inf,yr,xm,ym,d,mu,md,l,r;
int f[N][N],h,t,q[N*N][2],ans=inf;
int ul[N],ur[N],dl[N],dr[N],fu[N],fd[N],f11,f1n,fn1,fnn;
char a[N][N],ban[N][N];
inline void umin(int&a,int b){if(a>b)a=b;}
inline void umax(int&a,int b){if(a<b)a=b;}
inline void add(int x,int y,int z){
if(x<1||x>n||y<1||y>n)return;
if(ban[x][y]||~f[x][y])return;
if(x==1)umin(ans,z+xr-xm+1);
if(x==n)umin(ans,z+xm-xl+1);
if(y==1)umin(ans,z+yr-ym+1);
if(y==n)umin(ans,z+ym-yl+1);
if(x==1&&y==1)umin(ans,z+f11);
if(x==1&&y==n)umin(ans,z+f1n);
if(x==n&&y==1)umin(ans,z+fn1);
if(x==n&&y==n)umin(ans,z+fnn);
q[++t][0]=x,q[t][1]=y,f[x][y]=z;
}
int main(){
scanf("%d",&n);
for(i=1;i<=n;i++)for(scanf("%s",a[i]+1),j=1;j<=n;j++)if(a[i][j]=='r'){
umin(xl,i);
umax(xr,i);
umin(yl,j);
umax(yr,j);
}
for(i=xl;i<=xr;i++){
for(j=yl;j<=yr;j++)if(a[i][j]!='r')break;
if(j>yr)xm=i;
}
for(i=yl;i<=yr;i++){
for(j=xl;j<=xr;j++)if(a[j][i]!='r')break;
if(j>xr)ym=i;
}
for(i=xl;i<=xm;i++){
d=xm-i;
ul[d]=inf;ur[d]=0;
for(j=yl;j<=yr;j++)if(a[i][j]=='r'){
umin(ul[d],j);
umax(ur[d],j);
}
ul[d]=ym-ul[d];
ur[d]=ur[d]-ym;
}
for(i=xm;i<=xr;i++){
d=i-xm;
dl[d]=inf;dr[d]=0;
for(j=yl;j<=yr;j++)if(a[i][j]=='r'){
umin(dl[d],j);
umax(dr[d],j);
}
dl[d]=ym-dl[d];
dr[d]=dr[d]-ym;
}
mu=xm-xl;
md=xr-xm;
for(i=1;i<=n;i++)for(j=1;j<=n;j++)f[i][j]=0;
for(i=1;i<=n;i++){
fu[0]=fd[n+1]=inf;
for(j=1;j<=n;j++)if(a[j][i]=='X')fu[j]=0;else fu[j]=fu[j-1]+1;
for(j=n;j;j--)if(a[j][i]=='X')fd[j]=0;else fd[j]=fd[j+1]+1;
for(j=1;j<=n;j++){
l=n;
if(fu[j]<=mu)umin(l,i-ur[fu[j]]);
if(fd[j]<=md)umin(l,i-dr[fd[j]]);
r=1;
if(fu[j]<=mu)umax(r,i+ul[fu[j]]);
if(fd[j]<=md)umax(r,i+dl[fd[j]]);
umax(l,1),umin(r,n);
if(l<=r)f[j][l]++,f[j][r+1]--;
}
}
for(i=1;i<=n;i++)for(j=1;j<=n;j++){
f[i][j]+=f[i][j-1];
if(f[i][j])ban[i][j]=1;
}
f11=f1n=fn1=fnn=inf;
for(i=1;i<=md;i++){
umin(f11,i+dr[i]+1);
umin(f1n,i+dl[i]+1);
umin(fn1,i+ur[i]+1);
umin(fnn,i+ul[i]+1);
}
for(i=yl;i<=ym;i++){
d=ym-i;
ul[d]=inf;ur[d]=0;
for(j=xl;j<=xr;j++)if(a[j][i]=='r'){
umin(ul[d],j);
umax(ur[d],j);
}
ul[d]=xm-ul[d];
ur[d]=ur[d]-xm;
}
for(i=ym;i<=yr;i++){
d=i-ym;
dl[d]=inf;dr[d]=0;
for(j=xl;j<=xr;j++)if(a[j][i]=='r'){
umin(dl[d],j);
umax(dr[d],j);
}
dl[d]=xm-dl[d];
dr[d]=dr[d]-xm;
}
mu=ym-yl;
md=yr-ym;
for(i=1;i<=n;i++)for(j=1;j<=n;j++)f[i][j]=0;
for(i=1;i<=n;i++){
fu[0]=fd[n+1]=inf;
for(j=1;j<=n;j++)if(a[i][j]=='X')fu[j]=0;else fu[j]=fu[j-1]+1;
for(j=n;j;j--)if(a[i][j]=='X')fd[j]=0;else fd[j]=fd[j+1]+1;
for(j=1;j<=n;j++){
l=n;
if(fu[j]<=mu)umin(l,i-ur[fu[j]]);
if(fd[j]<=md)umin(l,i-dr[fd[j]]);
r=1;
if(fu[j]<=mu)umax(r,i+ul[fu[j]]);
if(fd[j]<=md)umax(r,i+dl[fd[j]]);
umax(l,1),umin(r,n);
if(l<=r)f[l][j]++,f[r+1][j]--;
}
}
for(i=1;i<=n;i++)for(j=1;j<=n;j++){
f[i][j]+=f[i-1][j];
if(f[i][j])ban[i][j]=1;
}
for(h=i=1;i<=n;i++)for(j=1;j<=n;j++)f[i][j]=-1;
add(xm,ym,0);
while(h<=t){
x=q[h][0],y=q[h++][1],z=f[x][y]+1;
add(x+1,y,z);
add(x-1,y,z);
add(x,y+1,z);
add(x,y-1,z);
}
if(ans<inf)printf("%d",ans);else puts("NIE");
return 0;
}

  

BZOJ1114 : [POI2008]鲁滨逊逃生Rob的更多相关文章

  1. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  2. [BZOJ1112][POI2008]砖块Klo

    [BZOJ1112][POI2008]砖块Klo 试题描述 N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另 ...

  3. [bzoj1122][POI2008]账本BBB

    1122: [POI2008]账本BBB Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 402  Solved: 202[Submit][Status ...

  4. HDU 4857 逃生 (反向拓扑排序 & 容器实现)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4857 逃生 Time Limit: 2000/1000 MS (Java/Others)    Mem ...

  5. 谷歌大牛 Rob Pike 的 5 个编程原则

    谷歌大牛 Rob Pike 的 5 个编程原则 简介: Rob Pike,目前谷歌公司最著名的软件工程师之一,曾是贝尔实验室Unix开发团队成员,Plan9操作系统开发的主要领导人,Inferno操作 ...

  6. BZOJ 1113: [Poi2008]海报PLA

    1113: [Poi2008]海报PLA Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1025  Solved: 679[Submit][Statu ...

  7. BZOJ 1116: [POI2008]CLO

    1116: [POI2008]CLO Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 922  Solved: 514[Submit][Status][ ...

  8. BZOJ 1112: [POI2008]砖块Klo

    1112: [POI2008]砖块Klo Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1736  Solved: 606[Submit][Statu ...

  9. BZOJ 1124: [POI2008]枪战Maf

    1124: [POI2008]枪战Maf Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 617  Solved: 236[Submit][Status ...

随机推荐

  1. 四、优化及调试--网站优化--Yahoo军规下

    21.根据域名划分页面内容 很显然, 是最大限度地实现平行下载 22.尽量减少iframe的个数 考虑即使内容为空,加载也需要时间,会阻止页面加载,没有语意,注意iframe相对于其他DOM元素高出1 ...

  2. 三、jQuery--Ajax基础--Ajax全接触--JSON

    JSON基本概念 JSON:JavaScript对象表示法(JavaScript Object Notation) JSON是存储和交换文本信息的语法,类似XML.它采用键值对的方式来组织,易于人们阅 ...

  3. 基于python网络编程实现支持购物、转账、存取钱、定时计算利息的信用卡系统

    一.要求 二.思路 1.购物类buy 接收 信用卡类 的信用卡可用可用余额, 返回消费金额 2.信用卡(ATM)类 接收上次操作后,信用卡可用余额,总欠款,剩余欠款,存款 其中: 1.每种交易类型不单 ...

  4. python实现支持并发、断点续传的Ftp程序

    一.要求 1.用户md5认证 2.支持多用户同时登陆(并发) 3.进入用户的命令行模式,支持cd切换目录,ls查看目录子文件 4.执行命令(ipconfig) 5.传输文件: a.支持断点续传 b.传 ...

  5. 图结构练习——判断给定图是否存在合法拓扑序列(dfs算法(第一个代码),邻接矩阵(前两个代码),邻接表(第三个代码))

    sdut 2140 图结构练习——判断给定图是否存在合法拓扑序列 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述  给定一个有向图 ...

  6. proxifier 代理bluestack

    proxycap 可以很方便的代理bluestack, 但是proxycap 的破解版现在越来越不好用了,而且不小心还会中个病毒,这个时候免费的proxifier就显得更加的可爱了. 但是有个问题,就 ...

  7. android 入门-防微信拍摄视频 按钮事件处理

    package com.cc.view; import com.cc.R; import com.cc.R.layout; import com.cc.R.menu; import android.o ...

  8. 自己动手写RTP服务器——关于RTP协议

    转自:http://blog.csdn.net/baby313/article/details/7353605 本文会带领着你一步步动手实现一个简单的RTP传输服务器,旨在了解RTP流媒体传输协议以及 ...

  9. ViewPager onPageChangeListener总结(转)

    android ViewPager滑动事件讲解 今天在做项目的时候,由于要处理viewPager页面滑动的事件,所以对其进行了一个小小的研究: 首先ViewPager在处理滑动事件的时候要用到OnPa ...

  10. hive中大表join

    排序存储数据至BUCKETS,这样可以顺序进行join