题:https://nanti.jisuanke.com/t/42397
题意:给定矩阵,若相邻位置比当前位置多1,那么就可以从当前位置走到此相邻位置,定义一条合法路径为经过位置数大于等于4,一条路径是能扩增就扩增,不能截取一段来做路径,问给定矩阵有多少条合法路径。
分析:在相邻点判断建有向边,用拓扑序去跑DAG,dp记录各自长度。
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define pb push_back const int M=1e3+3; const int N=2e6+6; const int mod=1e9+7; int a[M][M],in[N]; ll dp[N][5]; vector<int>g[N]; int nex[]={0,0,1,-1}; int ney[]={1,-1,0,0}; queue<int>que; int main(){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ for(int k=0;k<4;k++){ int tx=i+nex[k]; int ty=j+ney[k]; if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&a[i][j]==a[tx][ty]-1){ int u=(i-1)*m+j; int v=(tx-1)*m+ty; g[u].pb(v); in[v]++; } } } } for(int i=1;i<=n*m;i++) if(in[i]==0) que.push(i),dp[i][1]=1; ll ans=0; while(!que.empty()){ int now=que.front(); que.pop(); int f=0; for(auto v:g[now]){ dp[v][2]=(dp[v][2]+dp[now][1])%mod; dp[v][3]=(dp[v][3]+dp[now][2])%mod; dp[v][4]=(dp[v][4]+dp[now][3]+dp[now][4])%mod; if(--in[v]==0) que.push(v); f=1; } if(!f)///到点了 ans=(ans+dp[now][4])%mod; } printf("%lld ",ans); return 0; }