2019ICPC南京 Digital Path(拓扑排序+dp)

对于本题,可以发现是一种bfs不断向外扩展的情况,也就是当某个点周围所有比他小1的点都更新过他了,那么他才可以更新别人,这里就有一种拓扑排序的思想

又因为题目告诉我们要找最长的,因此我们最后的答案某点,不能向外扩展,因此可以维护出度和入度,以入度为更新标准,以出度为是否能作为答案

之后拓扑时直接修改dp值即可,表示i,j这个位置,长度为k的答案,这里直接将4以上的压缩到4,这样比较方便,并且满足复杂度。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int inf=0x3f3f3f3f;
const int N=2e5+10;
const int mod=1e9+7;
int f[2010][1010][5];
int n,m;
int a[2110][2010];
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
int in[2110][2010],out[2110][2010];
void topo(){
    queue<pll> q;
    int i,j;
    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++){
            if(!in[i][j]){
                q.push({i,j});
                f[i][j][1]=1;
            }
        }
    }
    while(q.size()){
        auto t=q.front();
        q.pop();
        i=t.first;
        j=t.second;
        for(int k=0;k<4;k++){
            int x=t.first+dx[k];
            int y=t.second+dy[k];
            if(x&&x<=n&&y&&y<=m){
                if(a[x][y]==a[i][j]+1){
                    f[x][y][2]=(f[x][y][2]+f[i][j][1])%mod;
                    f[x][y][3]=(f[x][y][3]+f[i][j][2])%mod;
                    f[x][y][4]=(f[x][y][4]+f[i][j][3]+f[i][j][4])%mod;
                    in[x][y]--;
                    if(!in[x][y])
                    q.push({x,y});
                }
            }
        }
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m;
    int i,j;
    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++){
            cin>>a[i][j];
        }
    }
    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++){
            for(int k=0;k<4;k++){
                int x=i+dx[k];
                int y=j+dy[k];
                if(x&&x<=n&&y&&y<=m){
                    if(a[i][j]==a[x][y]+1){
                        in[i][j]++;
                    }
                    if(a[i][j]==a[x][y]-1){
                        out[i][j]++;
                    }
                }
            }
        }
    }
    topo();
    ll ans=0;
    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++){
            if(!out[i][j]){
                ans=(ans+f[i][j][4])%mod;
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}
View Code

 

posted @ 2020-08-16 10:17  朝暮不思  阅读(231)  评论(0编辑  收藏  举报