洛谷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则绕来绕去必然超时。