题目来自洛谷1514 引水入城
很清新的一道搜索题,先造出每个蓄水厂的可浇灌区间,因为如果区间不连贯,必定会出现交叉相灌的情况,交叉意味着两条路都能走,假设不成立。
再贪心求得最小覆盖值,值得一说的是贪心用的方法是跳过大区间内包含的小区间,直到下一个与上一个r值不相交l值出现时答案才加一。
其他没什么好说的了。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int ans=99999999,maxn=99999999;
int m,n,cnt,fl,now;
int be[502],a[502][502],v[502][502];
struct llo{
int l,r;
} e[503],d[503];
int cmp(llo x,llo y){
if(x.l==y.l) return x.r>y.r;
return x.l<y.l;
}
void fugai(int num,int nx,int ny){
v[nx][ny]=1;
if(nx==n){
be[ny]=1;
e[num].l=min(e[num].l,ny);
e[num].r=max(e[num].r,ny);
}
if(nx!=1&&a[nx][ny]>a[nx-1][ny]&&v[nx-1][ny]==0){
fugai(num,nx-1,ny);
}
if(nx!=n&&a[nx][ny]>a[nx+1][ny]&&v[nx+1][ny]==0){
fugai(num,nx+1,ny);
}
if(ny!=1&&a[nx][ny]>a[nx][ny-1]&&v[nx][ny-1]==0){
fugai(num,nx,ny-1);
}
if(ny!=m&&a[nx][ny]>a[nx][ny+1]&&v[nx][ny+1]==0){
fugai(num,nx,ny+1);
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
}
}
for(int i=1;i<=m;i++) e[i].l=99999999;
for(int i=1;i<=m;i++){
memset(v,0,sizeof(v));
if(a[1][i]>=a[1][i-1]&&a[1][i]>=a[1][i+1]){
fugai(i,1,i);
}
}
for(int i=1;i<=m;i++){
if(be[i]==0) fl++;
}
if(fl!=0){
printf("0\n%d",fl);
return 0;
}
now=1;cnt=0;
for(int i=1;i<=m;i++){
if(e[i].l==99999999) continue;
cnt++;
d[cnt].l=e[i].l;
d[cnt].r=e[i].r;
}
now=1;int ccc=1;ans=0;
sort(d+1,d+cnt+1,cmp);
while(ccc<=m){
int numm=0;
while(d[now].l<=ccc){
printf("%d %d %d\n",d[now].l,ccc,d[now].r);
numm=max(numm,d[now].r);
now++;
}
ccc=numm+1;
ans++;
}
printf("1\n%d",ans);
return 0;
}
