题目来源:https://www.luogu.org/problem/show?pid=1514
水厂只能在湖泊旁建,如果能够满足要求,那么每一个水厂其输水可达的干旱区的城市一定是连续的。
对每一个靠近湖泊的城市bfs,求出其可达的干旱区的城市的区间左右端点。
如果bfs过程中有没被遍历到的城市,则为无解。
如果有解,则问题转化为了区间覆盖问题,运用贪心或dp解决。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int a[501][501];
int du[501];
int vis[501][501];
int start[501],end[501];
int f[521];
int q[1000001];
int main()
{
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
}
}
memset(start,63,sizeof(start));
memset(end,0,sizeof(end));
for(int j=1;j<=m;j++)
{
memset(vis,0,sizeof(vis));
int front=1,back=0;
vis[1][j]=1;
q[++back]=1;q[++back]=j;
while(front<=back)
{
int x=q[front++];
int y=q[front++];
if(x==n)
{
du[y]=1;
start[j]=min(start[j],y);
end[j]=max(end[j],y);
}
if(x-1>=1&&a[x-1][y]<a[x][y]&&vis[x-1][y]==0)
{
q[++back]=x-1;q[++back]=y;
vis[x-1][y]=1;
}
if(x+1<=n&&a[x+1][y]<a[x][y]&&vis[x+1][y]==0)
{
q[++back]=x+1;q[++back]=y;
vis[x+1][y]=1;
}
if(y-1>=1&&a[x][y-1]<a[x][y]&&vis[x][y-1]==0)
{
q[++back]=x;q[++back]=y-1;
vis[x][y-1]=1;
}
if(y+1<=m&&a[x][y+1]<a[x][y]&&vis[x][y+1]==0)
{
q[++back]=x;q[++back]=y+1;
vis[x][y+1]=1;
}
}
}
int cnt=0;
for(int i=1;i<=m;i++)if(du[i]==0)cnt++;
if(cnt)
{
cout<<"0"<<endl;
cout<<cnt;
return 0;
}
else cout<<"1"<<endl;
memset(f,63,sizeof(f));
f[0]=0;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=m;j++)
{
if(i>=start[j]&&i<=end[j])
{
f[i]=min(f[i],f[start[j]-1]+1);
}
}
}
cout<<f[m];
return 0;
}