题目传送门

这道题开始看好像并没有什么思路,和搜索好像也并没有什么关系。但是我们手玩下样例就会发现,思路其实就三句话:(写这道题的时候在代码里写的)

  • //我们想知道从第1行的每列往下到干旱区的范围

  • //要求这个直接bfs就行了

  • //然后就转换为了一个最小线段覆盖了

写了个bfs,在学长的blog那里看了看线段覆盖怎么搞,于是就交了,开始是30分,因为bfs的时候我只用了3个方向。开始以为它是不能向上建水站的,后来想想其实也可以,只要满足有公共边+高度有落差就行了...再交就90分了\(qwq\),T了一个点,开了氧气优化+快读,然后A了(???)

// luogu-judger-enable-o2
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue> using namespace std; int n,m,ans,tot;
int la[600][600],tong[600],fla[600];
bool vis[600][600];
int dx[5]={0,0,1,0,-1};
int dy[5]={0,-1,0,1,0};
struct segment{
int l,r;
}p[600]; void re(int &x)
{
x=0;
char ch=getchar();
bool flag=false;
while(ch<'0'||ch>'9') flag|=(ch=='-'),ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
x=flag ? -x : x;
} bool valid(int x,int y)
{
if(x>=1&&x<=n&&y>=1&&y<=m) return 1;
return 0;
} bool cmp(segment x,segment y)
{
return x.l<y.l;
} void bfs(int x,int y)
{
memset(vis,0,sizeof(vis));
queue<pair<int,int> >q;
q.push(make_pair(x,y));
vis[x][y]=1;
while(!q.empty())
{
int nx=q.front().first;
int ny=q.front().second;
q.pop();
for(int i=1;i<=4;i++)
{
int xx=nx+dx[i];
int yy=ny+dy[i];
if(valid(xx,yy)&&la[nx][ny]>la[xx][yy]&&!vis[xx][yy])
q.push(make_pair(xx,yy)),vis[xx][yy]=1;
}
}
int l=99999,r=0;
for(int j=1;j<=m;j++)
if(vis[n][j]) tong[y]++,fla[j]++,l=min(l,j),r=max(r,j);
if(!tong[y]) return ;
p[++tot].l=l,p[tot].r=r;
} int main()
{
//我们想知道从第1行的每列往下到干旱区的范围
//要求这个直接bfs就行了
//然后就转换为了一个最小线段覆盖了
re(n);re(m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
re(la[i][j]);
for(int j=1;j<=m;j++)
bfs(1,j);
// for(int j=1;j<=m;j++) printf("%d %d\n",p[j].l,p[j].r);
for(int j=1;j<=m;j++)
if(!fla[j]) ans++;
if(ans) {printf("0\n%d",ans);return 0;}
sort(p+1,p+tot+1,cmp);
int s=1;
for (int i=1;i<=m;i++)
{
int r=0;
for (int j=1;j<=m;j++)
if (p[j].l<=s&&p[j].r>=s) r=max(r,p[j].r);
ans++;
s=r+1;
if (s>m) break;
}
printf("1\n%d",ans);
return 0;
}

为什么会T呢?刚才我们的算法复杂度其实严格是\(O(n^3+nlogn+n^2)\)的。开始不解为什么搜索会是\(O(n^3)\),想了想后发现这是网格图,遍历所有点一遍是\(O(n^2)\)的。而本题极限数据\(500\),可能会跑到一亿,超时。

刚才我们有最直观的想法:从第一行的每列出发向下搜索,但事实上我们可以不对所有第一行的位置进行向下搜索。只对那些满足\(h[1][i]>=h[1][i-1]\)而且\(h[1][i]>=h[1][i+1]\)的点进行搜索。因为当前点如果不满足这些条件,那么它形成的区间一定可以被其他区间覆盖,这个区间就没什么用了。

// luogu-judger-enable-o2
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue> using namespace std; int n,m,ans,tot;
int la[600][600],tong[600],fla[600];
bool vis[600][600];
int dx[5]={0,0,1,0,-1};
int dy[5]={0,-1,0,1,0};
struct segment{
int l,r;
}p[600]; void re(int &x)
{
x=0;
char ch=getchar();
bool flag=false;
while(ch<'0'||ch>'9') flag|=(ch=='-'),ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
x=flag ? -x : x;
} bool valid(int x,int y)
{
if(x>=1&&x<=n&&y>=1&&y<=m) return 1;
return 0;
} bool cmp(segment x,segment y)
{
return x.l<y.l;
} void bfs(int x,int y)
{
memset(vis,0,sizeof(vis));
queue<pair<int,int> >q;
q.push(make_pair(x,y));
vis[x][y]=1;
while(!q.empty())
{
int nx=q.front().first;
int ny=q.front().second;
q.pop();
for(int i=1;i<=4;i++)
{
int xx=nx+dx[i];
int yy=ny+dy[i];
if(valid(xx,yy)&&la[nx][ny]>la[xx][yy]&&!vis[xx][yy])
q.push(make_pair(xx,yy)),vis[xx][yy]=1;
}
}
int l=99999,r=0;
for(int j=1;j<=m;j++)
if(vis[n][j]) tong[y]++,fla[j]++,l=min(l,j),r=max(r,j);
if(!tong[y]) return ;
p[++tot].l=l,p[tot].r=r;
} int main()
{
//我们想知道从第1行的每列往下到干旱区的范围
//要求这个直接bfs就行了
//然后就转换为了一个最小线段覆盖了
re(n);re(m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
re(la[i][j]);
for(int j=1;j<=m;j++)
if(la[1][j]>=la[1][j-1]&&la[1][j]>=la[1][j+1])
bfs(1,j);
// for(int j=1;j<=m;j++) printf("%d %d\n",p[j].l,p[j].r);
for(int j=1;j<=m;j++)
if(!fla[j]) ans++;
if(ans) {printf("0\n%d",ans);return 0;}
sort(p+1,p+tot+1,cmp);
int s=1;
for (int i=1;i<=m;i++)
{
int r=0;
for (int j=1;j<=m;j++)
if (p[j].l<=s&&p[j].r>=s) r=max(r,p[j].r);
ans++;
s=r+1;
if (s>m) break;
}
printf("1\n%d",ans);
return 0;
}

Luogu P1514引水入城【搜索】 By cellur925的更多相关文章

  1. [luogu]P1514 引水入城[搜索][记忆化][DP]

    [luogu]P1514 引水入城 引水入城 题目描述在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个N 行M 列的矩形 ,如下图所示,其中每个格 ...

  2. 洛谷P1514 引水入城 [搜索,区间DP]

    题目传送门 引水入城 题目描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个 N 行×M 列的矩形,如上图所示,其中每个格子都代表一座城市,每 ...

  3. 【luogu P1514 引水入城】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1514 // luogu-judger-enable-o2 #include <iostream> ...

  4. Luogu P1514 引水入城

    我承认我有点懒(洛谷已经发过题解了,但我发誓要坚持写博客) 这道题坑了我3天…… 首先一看就与染色问题类似,果断BFS(写DFS炸了) 先将最上面(靠近水)的一行全部扔进队列里,做一遍BFS 再对最下 ...

  5. [NOIp2010] luogu P1514 引水入城

    跟 zzy, hwx 等人纠结是否回去上蛋疼的董老板的课. 题目描述 如图所示.你有一个 N×MN\times MN×M 的矩阵,水可以从一格流到与它相邻的格子,需要满足起点的海拔严格高于终点海拔.定 ...

  6. LUOGU P1514 引水入城 (bfs)

    传送门 解题思路 拉了很长的战线,换了好几种写法终于过了..首先每个蓄水场一定是对沙漠造成连续一段的贡献,所以可以$bfs$出每种状态,然后做一次最小区间覆盖,但这样的复杂度有点高.就每次只搜那些比左 ...

  7. Luogu 1514 引水入城 (搜索,动态规划)

    Luogu 1514 引水入城 (搜索,动态规划) Description 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个N行M列的矩形,如上图 ...

  8. 洛谷 P1514 引水入城 解题报告

    P1514 引水入城 题目描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个 NN 行 \times M×M 列的矩形,如上图所示,其中每个格 ...

  9. 洛谷P1514 引水入城

    洛谷P1514 引水入城 原题链接 一道好题...细节真多 第一次提交90分,然后就GG了,不知从何改起 其实比较简单吧... 首先,一个点的水流向最后一排,一定可以形成一个区间. 不行的话肯定GG ...

随机推荐

  1. [洛谷P3941] 入阵曲

    题目背景 丹青千秋酿,一醉解愁肠. 无悔少年枉,只愿壮志狂. 入阵曲 题解在代码里. #include<iostream> #include<cstdio> #include& ...

  2. Linux就该这么学--命令集合2(系统状态检测命令)

    1.查看本机当前的网卡配置与网络状态等信息:(ifconfig [网络设备] [参数]) ifconfig 2.查看系统的内核名称.内核发行版.内核版本.节点名.硬件名称.硬件平台.处理器类型.操作系 ...

  3. iOS应用的入口自定义和事件处理的自定义

    iOS应用的入口自定义和事件处理的自定义 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: ...

  4. "php"正则表达式使用总结

    一直对php的正则表达式的理解不是很深刻,而且是很一知半解,所以把自己用的的正则表达式总结下,以后方便查阅,以后遇到正则表达式的时候然后再追加到该文档的后面: /** * php常用正则表达式 * p ...

  5. margin-top 为什么会影响父元素的 margin-top

    1.原因:  In this specification, the expression collapsing margins means that adjoining margins (no non ...

  6. Mongodb 官网驱动2.2.4.26版本 增,删 改,查,mongodb2.2.4.26

    Mongodb是3.2.7版本 最近在学习mongodb数据库在网上找到的都不是2.X版本以下的,因为驱动从2.X以后修改了很多,以前不支持linq现2.X也支持了, Mongodb 启动服务就不说了 ...

  7. 谈谈嵌套for循环的理解

    谈谈嵌套for循环的理解     说for的嵌套,先说一下一个for循环的是怎么用的.      这次的目的是为了用for循环输出一个乘法口诀表,一下就是我的一步步理解.    一.   语法:   ...

  8. 进程优先级、nice值

    进程cpu资源分配就是指进程的优先权(priority).优先权高的进程有优先执行权利.配置进程优先权对多任务环境的linux很有用,可以改善系统性能.还可以把进程运行到指定的CPU上,这样一来,把不 ...

  9. hdu-5596 GTW likes gt(模拟+优先队列)

    题目链接: GTW likes gt  Time Limit: 2000/1000 MS (Java/Others)  Memory Limit: 131072/131072 K (Java/Othe ...

  10. 「HNOI2004」「LuoguP2292」L语言(AC自动机

    题目描述 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章T是由若干小写字母构成.一个单词W也是由若干小写字母构成.一个字典D是若干个单词的 ...