洛谷:滑雪
知识点:记忆化搜索
记忆化搜索其实就是在你暴搜的时候,某些点可以由其他点转移的过程中已经确定答案了,这些点往往可以不用去搜索这样可以减少时间的复杂度
5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
ll a[1001][1001];
int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};
ll s[1001][1001];
//从i,j为起点的最大距离
ll ok[1001][1001];
ll n,m;
int dfs(int x,int y)
{
if(ok[x][y])return s[x][y];
//记忆化搜索
ok[x][y]=1;
for(int i=0;i<4;i++)
{
int nx=x+dx[i];
int ny=y+dy[i];
if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&(a[nx][ny]<a[x][y]))
{
dfs(nx,ny);
//因为是从高处向低处走所以nx,ny的坐标要小于x和y的坐标
s[x][y]=max(s[x][y],s[nx][ny]+1);
}
}
return s[x][y];
}
void cf()
{
//ll n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
//输入每一个点的高度
}
}
ll ans=-1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
ans=max(ans,1ll*dfs(i,j));
//以i,j为起点的可以滑雪的最大距离
}
}
cout<<ans+1<<endl;//注意这里要加1因为它自己本身滑到自己的话高度是1不是0这个非常坑
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
ll t;
t=1;
while(t--)
{
cf();
}
}
洛谷: 食物链计数
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
const int mod=80112002;
vector<ll>g[N];
ll cnt;
ll du[N];
ll indu[N];
ll st[N];//表示以i为起点的最长的食物链是多少
int dfs(int x)
{
if(st[x])return st[x];
if(du[x]==0)return 1;//如果以这个点为起点的点的出度为0说明以这个点为起点的食物链只有一条
//说明不止一条
ll sum=0;
for(int i=0;i<g[x].size();i++)
{
sum=(sum+dfs(g[x][i]))%mod;
}
st[x]=(sum)%mod;
return st[x];
}
void cf()
{
ll n,m;
cin>>n>>m;//生物的种类和被吃的关系图
for(int i=1;i<=m;i++)
{
ll x,y;
cin>>x>>y;
indu[y]++;//入度y--;
du[x]++;//出度x++
g[x].push_back(y);
//x-y直接连接一条边
}
ll ans=0;
for(int i=1;i<=n;i++)
{
if(indu[i]==0)
{
ans=(ans+dfs(i))%mod;
}
}
cout<<ans<<endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
t=1;
while(t--)
{
cf();
}
}
还有一道几乎一样的题目洛谷的3183食物链不过这题要求不可以单独一个点去做食物链
这很好办我们只需要去再判断一下
判断出度必须大于0
这样就可以了
if(indu[i]==0&&du[i]>0)
{
ans=(ans+dfs(i));
}
洛谷猫粮规划
当然sum>r的时候可以剪枝
每一次pos==n的时候我们就回溯
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
ll n,l,r;
ll cnt;
ll a[N];
void dfs(int pos,int sum)
{
//从pos的位置开始,总数是sum开始搜的时候的答案
if(sum>r)return;
if(pos==n)
{
if(sum>=l&&sum<=r)
{
cnt++;
}
return;//搜到一种的话就回溯
}
dfs(pos+1,sum);
dfs(pos+1,sum+a[pos+1]);//下一个位置选或者不选
}
void cf()
{
cin>>n>>l>>r;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
dfs(0,0);
cout<<cnt<<endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
t=1;
while(t--)
{
cf();
}
}