洛谷P1514 引水入城

洛谷P1514 引水入城

原题链接

一道好题。。。细节真多
第一次提交90分,然后就GG了,不知从何改起
其实比较简单吧。。。
首先,一个点的水流向最后一排,一定可以形成一个区间。
不行的话肯定GG
所以先大力dfs出每个点的区间。
dfs之后可以先check一下
无解就暴力乱搞
有解时贪心,最开始右端点为0,每次选择可以与右端点相连接的区间中右端点最右的(语文不好),加入进答案并且更新右端点直到覆盖全区间。
我什么时候才能1A一道noip题。。。

// It is made by XZZ
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
typedef long long ll;
il int gi(){
    rg int x=0,f=1;rg char ch=getchar();
    while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int n,m;
int h[510][510];
bool vis[510][510];
bool yes[510];
const int X[]={0,1,-1,0,0},Y[]={0,0,0,1,-1};
il vd dfs(int x,int y){
    vis[x][y]=1;
    if(x==n)yes[y]=1;
    rep(i,1,4){
#define xx x+X[i]
#define yy y+Y[i]
	if(vis[xx][yy]||h[xx][yy]>=h[x][y])continue;
	dfs(xx,yy);
    }
}
int l[510],r[510];
il vd check(){
    int prt=0;
    rep(i,1,m)if(!yes[i])++prt;
    if(!prt)return;
    printf("0
%d
",prt);
    exit(0);
}
int main(){
    n=gi(),m=gi();
    rep(i,1,n)rep(j,1,m)h[i][j]=gi();
    rep(i,0,m+1)vis[0][i]=vis[n+1][i]=1;
    rep(i,0,n+1)vis[i][0]=vis[i][m+1]=1;
    rep(i,1,m){
	rep(j,1,n)rep(k,1,m)vis[j][k]=0;
	if(h[1][i]<h[1][i-1]||h[1][i]<h[1][i+1])continue;
	dfs(1,i);
	l[i]=1,r[i]=m;
	while(!vis[n][l[i]])++l[i];
	while(!vis[n][r[i]])--r[i];
    }
    int nowr=0,ans=0;
    check();
    while(nowr<m){
	int res=0;
	rep(i,1,m)if(l[i]<=nowr+1&&r[i]>r[res])res=i;
	if(res==0)return 0;
	else nowr=r[res];
	++ans;
    }printf("1
%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/xzz_233/p/7422500.html