题解 洛谷P1958 【上学路线】

言归正传,闲言少叙,现在进入题目吧!

题目大意:

现在有一张地图,你要从坐标(1,1)处(左下角)走到坐标(n,m)处(右上角),中间有一些地方不能走,而且只允许向上或向右走。求一共有多少种走法?

乍一看题目,嗯,不怎么难,显然是一道动态规划(大佬们都称之为DP)题。那么,我们首先要考虑的,就是dp[i][j]表示什么。

对于巨佬来说是很简单的吧?

很容易想到,我们可以用dp[i][j]表示走到坐标(i,j)有多少种方案。

那么,最后要求的就是dp[n][m]。

1.初始化

dp[1][1]自然等于1。不知道的请回吧

正常情况下,dp[i][1]=1,dp[1][i]=1。

不过请注意:

有坑!!

如果a[i][1]不能行驶,那么它这个点(dp[i][1]),以及后面的(dp[i+1][1],dp[i+2][1]……)都无法走到0。

2.状态转移方程

分类讨论。

if(dp[i][j]==-1)
{
    continue;//此点不必运算
}
if(dp[i-1][j]==-1&&dp[i][j-1]==-1)
{
    dp[i][j]=-1;//此点不可能走到
}
if(dp[i-1][j]==-1&&dp[i][j-1]!=-1)
{
    dp[i][j]=dp[i][j-1];
}
if(dp[i][j-1]==-1&&dp[i-1][j]!=-1)
{
    dp[i][j]=dp[i-1][j];
}
if(dp[i][j-1]!=-1&&dp[i-1][j]!=-1)
{
    dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
//后三种是常规状态,即dp[i][j]就是从下边和左边来的,如果一边来不了,就只算另一边。
View Code

3.上代码

#include<bits/stdc++.h>
using namespace std;
int dp[17][17];
int main()
{
    int i,j;
    int n,m;
    cin>>n>>m;
    int q;
    cin>>q;
    for(i=1;i<=q;i++)
    {
        int tx,ty;
        cin>>tx>>ty;
        dp[tx][ty]=-1;
    }
    dp[1][1]=1;
    for(i=1;i<=n;i++)
    {
        if(dp[i][1]!=-1)
        {
            dp[i][1]=1;
        }
        else
        {
            break;
        }
    }
    for(i=1;i<=m;i++)
    {
        if(dp[1][i]!=-1)
        {
            dp[1][i]=1;
        }
        else
        {
            break;
        }
    }
    for(i=2;i<=n;i++)
    {
        for(j=2;j<=m;j++)
        {
            if(dp[i][j]==-1)
            {
                continue;
            }
            if(dp[i-1][j]==-1&&dp[i][j-1]==-1)
            {
                dp[i][j]=-1;
            }
            if(dp[i-1][j]==-1&&dp[i][j-1]!=-1)
            {
                dp[i][j]=dp[i][j-1];
            }
            if(dp[i][j-1]==-1&&dp[i-1][j]!=-1)
            {
                dp[i][j]=dp[i-1][j];
            }
            if(dp[i][j-1]!=-1&&dp[i-1][j]!=-1)
            {
                dp[i][j]=dp[i-1][j]+dp[i][j-1];
            }
        }
    }
    cout<<dp[n][m]<<endl;
    return 0;
}
View Code

无注释版,有注释版在模块2当中。

点个赞再走吧!

#include<bits/stdc++.h>
using namespace std;
int dp[17][17];
int main()
{
    int i,j;
    int n,m;
    cin>>n>>m;
    int q;
    cin>>q;
    for(i=1;i<=q;i++)
    {
        int tx,ty;
        cin>>tx>>ty;
        dp[tx][ty]=-1;
    }
    dp[1][1]=1;
    for(i=1;i<=n;i++)
    {
        if(dp[i][1]!=-1)
        {
            dp[i][1]=1;
        }
        else
        {
            break;
        }
    }
    for(i=1;i<=m;i++)
    {
        if(dp[1][i]!=-1)
        {
            dp[1][i]=1;
        }
        else
        {
            break;
        }
    }
    for(i=2;i<=n;i++)
    {
        for(j=2;j<=m;j++)
        {
            if(dp[i][j]==-1)
            {
                continue;
            }
            if(dp[i-1][j]==-1&&dp[i][j-1]==-1)
            {
                dp[i][j]=-1;
            }
            if(dp[i-1][j]==-1&&dp[i][j-1]!=-1)
            {
                dp[i][j]=dp[i][j-1];
            }
            if(dp[i][j-1]==-1&&dp[i-1][j]!=-1)
            {
                dp[i][j]=dp[i-1][j];
            }
            if(dp[i][j-1]!=-1&&dp[i-1][j]!=-1)
            {
                dp[i][j]=dp[i-1][j]+dp[i][j-1];
            }
        }
    }
    cout<<dp[n][m]<<endl;
    return 0;
}
posted @ 2020-08-08 15:32  Bushuai_Tang  阅读(284)  评论(0编辑  收藏  举报