Codeforces 1214D. Treasure Island

題意:

給你一個nmn*m的地圖,有一些不能到達的點,用#表示,有個人要從(1,1)(1,1)(n,m)(n,m)點,你可以將其中任意點變成#,問你最少將多少個點變成#可以讓這個人無法到達(n,m)(n,m)

分析與解答

①對於一開始便無法到達的點來說,不需要變任何一個
②因爲(n,m)(n,m)點在左下角,我們只要放置(n1,m)(n - 1,m)(n,m1)(n,m - 1)兩個就可以不讓他到達
因此只需要考慮是否只放一個點就能夠阻止他

我們考慮dp[i][j]dp1[i][j]dp[i][j]、dp1[i][j]兩個dpdp數組,意義如下:
dp[i][j]:從(1,1)到(i,j)有多少種走法
dp1[i][j]:從(n,m)(n,m)(i,j)(i,j)有多少種走法,也就是從(i,j)(i,j)(n,m)(n,m)有多少種走法
對於一個點來說,如果滿足dp1[i][j]dp[i][j]==dp[n][m]dp1[i][j] * dp[i][j] == dp[n][m],則我們根據乘法定理,可以知道該點一定是一個必經點

同時考慮到數據範圍的問題,我們利用哈希的思想,對數組取模,如果在模aa和模bb的意義下,其中gcd(a,b)==1gcd(a,b) == 1,該點都滿足上邊的等式,則該點爲必經點

代碼

/*************************************************************************
	> File Name: 2019_9_4_4.cpp
	> Author: z472421519
	> Mail:
	> Created Time: 2019年09月04日 星期三 18時10分04秒
 ************************************************************************/
 
#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
#define MAXN 1000003
#define mod 1000000017
#define mod1 1000000007
#define ll long long
using namespace std;
 
vector <ll> dp[MAXN];
vector <ll> dp1[MAXN];
vector <ll> dp_[MAXN];
vector <ll> dp1_[MAXN];
string s[MAXN];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
 
    dp[1].push_back(1);
    dp_[1].push_back(1);
    //dp[1].push_back(1);
    for(int i = 1;i <= n;i++)
    {
        //rintf("T\n");
        cin >> s[i];
        //printf("T\n");
        for(int j = 0;j < m;j++)
        {
            dp1[i].push_back(0);
            dp1_[i].push_back(0);
            //printf("%d\n",i);
            if(i == 1 && j == 0)
                continue;
            if(s[i][j] == '#')
            {
                dp[i].push_back(0);
                dp_[i].push_back(0);
            }
            else
            {
                ll res = 0,res_ = 0;
                if(i > 1)
                {
                    res += dp[i - 1][j];
                    res_ += dp_[i - 1][j];
                }
                res %= mod;
                res_ %= mod1;
                if(j > 0)
                {
                    res += dp[i][j - 1];
                    res_ += dp_[i][j - 1];
                }
                res %= mod;
                res_ %= mod1;
                dp[i].push_back(res);
                dp_[i].push_back(res_);
            }
        }
        //printf("%d\n",dp[n][m - 1]);
    }
    if(dp[n][m - 1] == 0 && dp_[n][m - 1] == 0)
        printf("0\n");
    else
    {
        int ans = 2;
        dp1[n][m - 1] = 1;
        dp1_[n][m - 1] = 1;
        //printf("%d\n",dp1[n][m - 1]);
        for(int i = n;i >= 1;i--)
        {
            for(int j = m - 1;j >= 0;j--)
            {
                if(i == 1 && j == 0)
                    continue;
                if(i == n && j == m - 1)
                    continue;
                if(s[i][j] == '#')
                {
                    dp1[i][j] = 0;
                    dp1_[i][j] = 0;
                }
                else
                {
                    ll res = 0,res_ = 0;
                    if(i < n)
                    {
                        res += dp1[i + 1][j];
                        res_ += dp1_[i + 1][j];
                    }
                    res %= mod;
                    res_ %= mod1;
                    if(j < m - 1)
                    {
                        res += dp1[i][j + 1];
                        res_ += dp1_[i][j + 1];
                    }
                    res %= mod;
                    res_ %= mod1;
                    dp1[i][j] = res;
                    dp1_[i][j] = res_;
                    //printf("%d %d\n",i,j,dp[i][j],dp1[i][j],dp[n][m - 1]);
                    if((dp1[i][j] * dp[i][j]) % mod == dp[n][m - 1] && (dp1_[i][j] * dp_[i][j]) % mod1 == dp_[n][m - 1])
                    {
                        ans = 1;
                        break;
                    }
                //printf("%d %d %d %d\n",i,j,dp[i][j],dp1[i][j]);
                }
            }
            if(ans == 1)
                break;
            //printf("%d %d %d %d\n",i,j,dp[i][j],dp1[i][j]);
        }
        printf("%d\n",ans);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章