codevs 1066 引水入城
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codevs 1066 引水入城相关的知识,希望对你有一定的参考价值。
我的妈呀这题卡了我两天。
其实很简单的,就每个起点向下bfs,控制的连续的一段干旱区。然后就转换成了用最少的线段覆盖完所有区域的dp问题。
然而?!!我一开始不知道怎么写了个神奇的贪心。。。悲惨的世界。
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=505;
struct seg
{
int left,right;
}s[maxn*3];
int map[maxn][maxn],n,m;
int dx[]={0,0,1,0,-1},dy[]={0,-1,0,1,0},cnt=0,dp[maxn];
bool vis[maxn][maxn],k[maxn];
queue <int> q;
bool cmp(seg x,seg y)
{
if (x.left==y.left)
return x.right>y.right;
return x.left<y.left;
}
bool judge(int x,int y)
{
if ((x>=1) && (x<=n) && (y>=1) && (y<=m) && (vis[x][y]==false))
return true;
return false;
}
void bfs(int x)
{
memset(vis,false,sizeof(vis));
while (!q.empty())
q.pop();
int minn=99999999,maxn=0;
if (n==1)
{
minn=min(minn,x);
maxn=max(maxn,x);
k[x]=true;
}
vis[1][x]=true;
q.push(x);
while (!q.empty())
{
int head=q.front();
q.pop();
int nx,ny,tx,ty;
if (head%m==0) nx=head/m;
else nx=head/m+1;
if (head-nx*m==0) ny=m;
else ny=head-(nx-1)*m;
for (int i=1;i<=4;i++)
{
int tx=nx+dx[i],ty=ny+dy[i];
if ((judge(tx,ty)==true) && (map[nx][ny]>map[tx][ty]))
{
q.push((tx-1)*m+ty);
vis[tx][ty]=true;
if (tx==n)
{
minn=min(minn,ty);
maxn=max(maxn,ty);
k[ty]=true;
}
}
}
}
cnt++;
s[cnt].left=minn;
s[cnt].right=maxn;
}
int main()
{
memset(k,false,sizeof(k));
memset(dp,0x3f,sizeof(dp));
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
scanf("%d",&map[i][j]);
for (int i=1;i<=m;i++)
if ((map[1][i]>=map[1][i-1]) && (map[1][i]>=map[1][i+1]))
bfs(i);
int num=0;
for (int i=1;i<=m;i++)
if (k[i]==false)
num++;
if (num>0)
{
printf("0\n%d\n",num);
return 0;
}
sort(s+1,s+cnt+1,cmp);
dp[0]=0;
for (int i=1;i<=m;i++)
for (int j=1;j<=cnt;j++)
if ((s[j].left<=i) && (s[j].right>=i))
dp[i]=min(dp[i],dp[s[j].left-1]+1);
printf("1\n%d\n",dp[m]);
return 0;
}
以上是关于codevs 1066 引水入城的主要内容,如果未能解决你的问题,请参考以下文章