牛跳房子【USACO15FEB金组】【递推】

洛谷P3120题目链接

难度:普及-(我是蒟蒻)

原本是为了练线段树的,结果这题跟线段树毫无关系-_-

我犯的错误

一看到这道题,第一反应是深搜dfs,于是就有了以下代码:

#include<bits/stdc++.h>
using namespace std;
int r,c,k;
int a[751][751];
long long ans=0;
bool book[751][751]={0};
void dfs(int x,int y)
{
    if(x==r-1&&y==c-1)
    {
        ans=(ans+1)%1000000007;
        return;
    }
    for(int i=x+1;i<r;i++)
        for(int j=y+1;j<c;j++)
            if(a[i][j]!=a[x][y]&&book[i][j]==0)
            {
                book[i][j]=1;
                dfs(i,j);
                book[i][j]=0;
            }
    return;
}
int main()
{
    scanf("%d%d%d",&r,&c,&k);
    for(int i=0;i<r;i++)
        for(int j=0;j<c;j++)
            scanf("%d",&a[i][j]);
    dfs(0,0);
    cout<<ans<<endl;
    return 0;
}

一共15个点,4个AC,11个TLE

后来想想,是不是可以用递推。思前想后,回来看了看dfs代码,突然发现book是不需要的,我这个蒟蒻赶紧删了book相关的代码,自以为万事大吉。

#include<bits/stdc++.h>
using namespace std;
int r,c,k;
int a[751][751];
long long ans=0;
bool book[751][751];
void dfs(int x,int y)
{
    if(x==r-1&&y==c-1)
    {
        ans=(ans+1)%1000000007;
        return;
    }
    for(int i=x+1;i<r;i++)
        for(int j=y+1;j<c;j++)
            if(a[i][j]!=a[x][y])
            {
                //book[i][j]=1;
                dfs(i,j);
                //book[i][j]=0;
            }
    return;
}
int main()
{
    scanf("%d%d%d",&r,&c,&k);
    for(int i=0;i<r;i++)
        for(int j=0;j<c;j++)
            scanf("%d",&a[i][j]);
    dfs(0,0);
    cout<<ans<<endl;
    return 0;
}

一共15个点,4个AC,11个TLE

是的,book数组对时间复杂度并无较大影响。

正解

怎么办呢

赌一把,用递推!

于是就有了四重循环恐怖代码:(思路见注释)

#include<bits/stdc++.h>
using namespace std;
int r,c,k;                              //行,列,数值限定 
int a[751][751];
long long f[751][751]={0};           
                                        //f[i][j]=(i,j)严格左上方所有点的路径总数之和 
int main()
{
    scanf("%d%d%d",&r,&c,&k);
    for(int i=0;i<r;i++)
        for(int j=0;j<c;j++)
            scanf("%d",&a[i][j]);
    f[0][0]=1;
    for(int i=0;i<r;i++)
        for(int j=0;j<c;j++)            //要计算的点 
            for(int p=0;p<i;p++)
                for(int q=0;q<j;q++)    //左上方的点 
                    if(a[i][j]!=a[p][q])//审题:要求数值不同 
                        f[i][j]=(f[i][j]+f[p][q])%1000000007;
                                        //勿忘mod 1000000007  
    cout<<f[r-1][c-1]<<endl;
    return 0;
}

一共15个点,15个AC

蒟蒻后来想了想,f数组防止一个点重复计算,dfs则绕来绕去必然超时。

猜你喜欢

转载自blog.csdn.net/fail_perfectly/article/details/81510073