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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章