蒟蒻改了很久,终于,写篇题解总结总结
1.大致思路
观察题面,我们可以总结出几个比较关键的要点
-
水域会流动,并且需要有一定条件才能进行流动,可以想到用 b f s bfs bfs 去模拟水的流动。
-
需要判断水流是否能灌溉干旱线,可以使用 b f s bfs bfs 来判断。
根据大致对题面的了解,我们大致可以知道第一问需要用搜索解决,第二问待会儿考虑。
2.BFS
因为我们先开始不知道需要几个输水站,所以最好的情况就是用所有的输水站输水,如果用上了全部的输水站还不行,那肯定就不可以了。关于如何详细的打,这里就不细讲了。
void bfs(int x,int y){
queue<node>q;
t1.x=x,t1.y=y;
q.push(t1);
while(!q.empty()){
t1=q.front();
q.pop();
rep(i,0,3){
int dx=t1.x+dir[i][0],dy=t1.y+dir[i][1];
if(dx>=1 && dx<=n && dy>=1 && dy<=m && flag[dx][dy]==0){
if(a[t1.x][t1.y]>a[dx][dy]){
flag[dx][dy]=1;
t2.x=dx;
t2.y=dy;
q.push(t2);
}
}
}
}
}
3.第二问
- 确定方法
此题需要使用区间覆盖来解决。(想不通看下面)
- 确定区间
首先区间问题一类的需要区间,此题区间是什么呢?是每个输水站能输到的最左端和最右端。
- 证明区间连续
大家可能会问,输水站所运到的区间可能是不连续的,下面我们来证明实际上如果可以灌溉所有的干旱线,那么每个输水站所能运到水的区间一定是连续的。
黄色的表示一个输水站所运输的水,最后一行就是他所运到的地方,我们假设他是不连续的。
这是另一个输水站的运输路线,因为需要让最后一行所有的都覆盖,所以必须要经过绿色的点,而我们发现,绿色是黄色部分与绿色部分相交的部分,那么就可以知道黄色部分必定是不连续的,与我们假设的相反。因此,得证:如果可以灌溉所有的干旱线,那么每个输水站所能运到水的区间一定是连续的。
- 实现
已经证明完了,则可以使用区间覆盖来解决。
细节很多,需要细细品味。
int ans=0,s=1,t=m,lastr=1;
sort(qj,qj+1+m,cmp);
rep(i,1,m){
if(s>t) break;
int p=-INF;
rep(j,1,m){
if(s<qj[j].l) break;
p=max(p,qj[j].r);
}
ans++;
s=p+1;
}
c o d e code code
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define INF 0x7f7f7f7f
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define dep(i,r,l) for(int i=r;i>=l;i--)
using namespace std;
const int N=5e2+5;
const int M=5e2+5;
int n,m;
int a[N][M],flag[N][M],dir[4][2]={{1,0},{0,1},{0,-1},{-1,0}},Y;
struct node{
int x,y;
}t1,t2;
struct node_dp{
int l,r;
}qj[M];
bool cmp(node_dp x,node_dp y){
if(x.l!=y.l) return x.l<y.l;
return x.r>y.r;
}
void bfs(int x,int y){
queue<node>q;
t1.x=x,t1.y=y;
q.push(t1);
while(!q.empty()){
t1=q.front();
q.pop();
rep(i,0,3){
int dx=t1.x+dir[i][0],dy=t1.y+dir[i][1];
if(dx>=1 && dx<=n && dy>=1 && dy<=m && flag[dx][dy]==0){
if(a[t1.x][t1.y]>a[dx][dy]){
flag[dx][dy]=1;
t2.x=dx;
t2.y=dy;
q.push(t2);
}
}
}
}
}
int main(){
scanf("%d %d",&n,&m);
rep(i,1,n)
rep(j,1,m)
scanf("%d",&a[i][j]);
rep(i,1,m) flag[1][i]=1;
rep(i,1,m) bfs(1,i);
rep(i,1,m){
if(flag[n][i]==0){
Y=1;
break;
}
}
if(Y==1){
puts("0");
int ansN=0;
rep(i,1,m) ansN+=abs(flag[n][i]-1);
printf("%d",ansN);
}
else{
puts("1");
rep(i,1,m){
memset(flag,0,sizeof(flag));
flag[1][i]=1;
bfs(1,i);
rep(j,1,m){
if(flag[n][j]==1){
qj[i].l=j;
break;
}
}
dep(j,m,1){
if(flag[n][j]==1){
qj[i].r=j;
break;
}
}
}
int ans=0,s=1,t=m,lastr=1;
sort(qj,qj+1+m,cmp);
rep(i,1,m){
if(s>t) break;
int p=-INF;
rep(j,1,m){
if(s<qj[j].l) break;
p=max(p,qj[j].r);
}
ans++;
s=p+1;
}
printf("%d",ans);
}
return 0;
}