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; }
没有人不辛苦,只有人不喊疼