1. 程式人生 > 實用技巧 >2019ICPC南京 Digital Path(拓撲排序+dp)

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