luoguP1514 引水入城

Posted dream-runner

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luoguP1514 引水入城相关的知识,希望对你有一定的参考价值。

一道挺水的记忆化搜索的题。。。

注意一个点即可,每个点衍生的河流只会在干旱区形成连续的一段,不会分成多个小段。

证明很简单- - 

技术分享图片
#include<bits/stdc++.h>
using namespace std;
const int maxn=510,inf=99999999;
int l[maxn],r[maxn],tx[5]={0,1,-1,0,0},ty[5]={0,0,0,1,-1},a[maxn][maxn],n,m,f[maxn];
bool book[maxn][maxn],ans2[maxn];
typedef pair<int,int> P;
P b[maxn][maxn];
P dfs(int x,int y){
    P ret;
    ret.first=inf;ret.second=-inf;
    if(book[x][y])return b[x][y];
    if(x==n){
        ans2[y]=1;
        ret.first=l[y];
        ret.second=r[y];
    }
    book[x][y]=1;
    for(int i=1;i<=4;++i){
        int xx=tx[i]+x,yy=ty[i]+y;
        if(xx<1||xx>n||yy<1||yy>m||a[xx][yy]>=a[x][y])continue;
        P t=dfs(xx,yy);
        ret.first=min(ret.first,t.first);
        ret.second=max(ret.second,t.second);
    }
    b[x][y]=ret;
    return ret;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;++i){
        for(int j=1;j<=m;++j)cin>>a[i][j];
    }
    l[1]=1;r[m]=m;
    for(int i=2;i<=m;++i){
        if(a[n][i-1]<a[n][i])l[i]=l[i-1];
        else l[i]=i;
    }
    
    for(int i=m-1;i>=1;--i){
        if(a[n][i+1]<a[n][i])r[i]=r[i+1];
        else r[i]=i;
    }
    for(int i=1;i<=m;++i){
        P t=dfs(1,i);
        if(t.first!=inf)
        f[t.first]=max(f[t.first],t.second);
    }
    int cnt=0;
    for(int i=1;i<=m;++i){
        if(!ans2[i])++cnt;
    }
    if(cnt!=0){
        cout<<0<<endl<<cnt;
    }
    else{
        cout<<1<<endl;
        for(int i=1;i<=m;++i){
            f[i]=max(f[i-1],f[i]);
        }
        int k=0,ans=0;
        while(k!=m){
            k=f[k+1];
            ++ans;
        }
        cout<<ans;
    }
    return 0;
}
View Code

 

以上是关于luoguP1514 引水入城的主要内容,如果未能解决你的问题,请参考以下文章

luoguP1514 引水入城 x

Luogu_P1514 引水入城 记忆化搜索

P1514 引水入城

P1514 引水入城

洛谷 P1514 引水入城

洛谷P1514 引水入城