链接:https://nanti.jisuanke.com/t/42397
题意:求图中所要求的线段的数量
题解:dfs+dp,第一次知道dp还能这样玩.....
对于每一位置先判断是否为起点,如果上下左右进入数量为1即为起点
下来因为要求要长度最少为4,所以开三维dp数组进行计数
图片说明 表示对于第i行第j列的位置,以此为终点的长度为k的情况有多少个
下来就是对于起点进行广搜,对于可以到达的每个点都进行dp数组更新,如果到那个位置他的入度变为0,加入数组,因为如果入度不为0直接加入会有后效性,影响结果

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e3+10,p=1e9+7;
const int dx[]={0,1,0,-1},dy[]={1,0,-1,0};
int n,m,g[N][N],in[N][N],out[N][N],dp[N][N][5],res;
void top_sort(){
    queue<pair<int,int> > q;
    for(int i=1;i<=n;i++)    for(int j=1;j<=m;j++)    if(!in[i][j]){
        q.push({i,j});    dp[i][j][1]=1;
    }
    while(q.size()){
        int ux=q.front().first,uy=q.front().second; q.pop();
        for(int i=0;i<4;i++){
            int tx=ux+dx[i],ty=uy+dy[i];
            if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&g[tx][ty]==g[ux][uy]+1){
                dp[tx][ty][2]=(dp[tx][ty][2]+dp[ux][uy][1])%p;
                dp[tx][ty][3]=(dp[tx][ty][3]+dp[ux][uy][2])%p;
                dp[tx][ty][4]=(dp[tx][ty][4]+dp[ux][uy][3]+dp[ux][uy][4])%p;
                if(--in[tx][ty]==0)    q.push({tx,ty});
            }
        }
    }
}
signed main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)    for(int j=1;j<=m;j++)    scanf("%lld",&g[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+dx[k],ty=j+dy[k];
                if(tx>=1&&tx<=n&&ty>=1&&ty<=m){
                    if(g[tx][ty]==g[i][j]+1)    out[i][j]++;
                    if(g[tx][ty]==g[i][j]-1)    in[i][j]++;
                }
            }
    top_sort();
    for(int i=1;i<=n;i++)    for(int j=1;j<=m;j++)    if(!out[i][j]){
        res=(res+dp[i][j][4])%p;
    }
    cout<<res<<endl;
    return 0;
}