题目:引水入城
思路:
一次dfs求出第一排每个点建蓄水场可以覆盖的点。
然后求最小区间覆盖。
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 500
#define read(x) scanf("%d",&x)
struct Pair{
int x,y;
Pair(){}
bool operator < (const Pair& oth) const {
return x<oth.x||(x==oth.x&&y<oth.y);
}
};
int n,m;
int a[maxn+5][maxn+5];
int f[maxn+5][maxn+5];
int vis[maxn+5][maxn+5];
vector<int> g[maxn+5];
const int m1[10]={0,0,0,1,-1};
const int m2[10]={0,1,-1,0,0};
Pair b[maxn+5];
void dfs(int x,int y) {
if(x<1||x>n||y<1||y>m) return;
if(vis[x][y]) return ;
vis[x][y]=f[x][y]=true;
for(int i=1;i<=4;i++) {
if(a[x+m1[i]][y+m2[i]]<a[x][y]) dfs(x+m1[i],y+m2[i]);
}
}
int main() {
read(n),read(m);
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
read(a[i][j]);
}
}
for(int i=1;i<=m;i++) {
memset(vis,0,sizeof(vis));
if(!f[1][i]) dfs(1,i);
for(int j=1;j<=m;j++) {
if(vis[n][j]&&!b[i].x) b[i].x=j;
if(vis[n][j]) b[i].y=j;
}
}
sort(b+1,b+m+1);
int cnt=0;
for(int i=1;i<=m;i++) {
if(!f[n][i]) cnt++;
}
if(cnt) {printf("0\n%d",cnt);return 0;}
printf("1\n");
int d=0,ans=0;
b[m+1].x=(int)1e9;
for(int i=1;i<=m;i++) {
if(b[i+1].x>d+1&&b[i].y>d) d=max(d,b[i].y),ans++;
}
printf("%d",ans);
return 0;
}