2019ICPC南京-C-Digital Path(BFS+dp记录)

题目链接

题意

给了一个路径的定义,每次严格+1的走,能走的必须要走。求这样的路径长度大于4的有多少个。

思路

BFS搜索,但有个问题是如果两条路,有很大一部分是重复的,应该只走一遍。

用入度出度,in,out记录,如果入度为0,则是起点,如果出度为0,则是终点。所有的起点入队,BFS。每次到达一个点,先让该点的入度减一,如果变为0,则入队。这样如果一个点有多个入度,就会只走一次。

用dp记录每个点的信息,到达该点的路径长度分别为1,2,3,大于等于4的路径个数。状态转移的时候,长度1变为长度2,长度2变为长度3,长度3变为长度4。但是dp[4][x][y]的含义是大于等于4的路径个数,所以大于等于4的加上1还是大于等于4,也要加上去。

 

所以是想到了重复的路径要只走一次,用数组记录信息,但是不知道怎么处理。

想想入度出度,dp数组情况都开就完事了,QAQ


#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long

using namespace std;

const int N = 1010;
const int mod = 1e9+7;

struct node
{
    int x,y;
    node(){}
    node(int xx,int yy):x(xx),y(yy){}
};

int m,n;
int a[N][N],dp[5][N][N],in[N][N],out[N][N];
int dir[4][2] = {0,1,0,-1,1,0,-1,0};

bool valid(int x,int y)
{
    if(x<1||y<1||x>m||y>n) return false;
    else return true;
}

void Add(int i,int j,int x,int y)
{
    dp[2][x][y] = (dp[2][x][y] + dp[1][i][j])%mod;
    dp[3][x][y] = (dp[3][x][y] + dp[2][i][j])%mod;
    dp[4][x][y] = (dp[4][x][y] + dp[3][i][j] + dp[4][i][j])%mod;
}
int main()
{
    scanf("%d%d",&m,&n);
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            scanf("%d",&a[i][j]);
        }
    }
    queue <node> Q;

    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            for(int k=0;k<4;k++){
                int tx = i + dir[k][0];
                int ty = j + dir[k][1];
                if(valid(tx,ty)==0) continue;
                if(a[tx][ty]==a[i][j]+1) out[i][j]++;
                if(a[tx][ty]==a[i][j]-1) in[i][j]++;

            }
            if(in[i][j]==0) {Q.push(node(i,j));dp[1][i][j]++;}
        }
    }

    node p;
    while(!Q.empty())
    {
        p = Q.front(); Q.pop();
        for(int k=0;k<4;k++){
            int tx = p.x + dir[k][0];
            int ty = p.y + dir[k][1];
            if(valid(tx,ty)==0) continue;
            if(a[tx][ty]!=a[p.x][p.y]+1) continue;
            Add(p.x,p.y,tx,ty);
            in[tx][ty]--;
            if(in[tx][ty]==0) Q.push(node(tx,ty));
        }
    }

    int ans = 0;
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            if(out[i][j]==0) ans = (ans + dp[4][i][j])%mod;
        }
    }

    printf("%d",ans);

    return 0;
}

 

发布了62 篇原创文章 · 获赞 29 · 访问量 4748
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章