ABC 240 C - Jumping Takahashi(dp)
https://atcoder.jp/contests/abc240/tasks/abc240_c
题目大意:
给定n个点,每个点有ai和bi这两种正整数的位置
让我们用n次跳跃,实现从0的位置跳到x的位置上
可以的话输出Yes,不可以的话输出No
Sample Input 1
2 10
3 6
4 5
Sample Output 1
Yes
Sample Input 2
2 10
10 100
10 100
Sample Output 2
No
Sample Input 3
4 12
1 8
5 7
3 4
2 6
Sample Output 3
Yes
一种爆时写法
自从学会了dfs,越来越能写爆时写法了
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=200200,M=2002;
LL a[N],b[N];
LL n,x,sum=0;
bool flag=false;
void dfs(LL idx,LL sum)
{
if(idx==n+1)
{
if(sum==x) flag=true;
return ;
}
if(sum>x) return ;
if(sum+a[idx]<=x) dfs(idx+1,sum+a[idx]);
if(sum+b[idx]<=x) dfs(idx+1,sum+b[idx]);
}
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
LL T=1;
//cin>>T;
while(T--)
{
cin>>n>>x;
for(LL i=1;i<=n;i++)
cin>>a[i]>>b[i];
dfs(1,0);
if(flag==true) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
正解如下
代码内部有详细注释
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=200200,M=2002;
int a[N],b[N],f[120][10200];
int n,x;
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
int T=1;
//cin>>T;
while(T--)
{
memset(f,0,sizeof f);
cin>>n>>x;
for(int i=0;i<n;i++)
cin>>a[i]>>b[i];
//当我在第一个格子的时候,但是还没有选择移动,所以初始化为1
//这个表示的是在面对第i个格子的时候,我能不能到达第j的位置
f[0][0]=1;
for(int i=0;i<n;i++)//这n种类的步数都要有所选择
{
for(int j=0;j<=x;j++)//j必须要从前面跳到x,因为正整数是累加的
{
if(f[i][j])
{
//这一步选择a没事,可以直接跳,标注一下
//跳了一步跳到了当前坐标的下一行,总数是j+a[i]
if(j+a[i]<=x) f[i+1][j+a[i]]=1;
//这一步选择b也可以,直接跳,然后标记
if(j+b[i]<=x) f[i+1][j+b[i]]=1;
}
}
}
//如果在这一行的x的这个位置已经标记过了,说明在前n次操作中,我能够跳到n的位置
if(f[n][x]) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
因为我比较习惯下标从1开始,所以改进了一下写法
就变成了下面酱紫
感觉这个理解起来也相对容易一些
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=200200,M=2002;
int a[N],b[N],f[120][10200];
int n,x;
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
int T=1;
//cin>>T;
while(T--)
{
memset(f,0,sizeof f);
cin>>n>>x;
for(int i=1;i<=n;i++)
cin>>a[i]>>b[i];
//当前我已经走了0步数,走到了0的位置
//这个是默认条件
f[0][0]=1;
for(int i=1;i<=n;i++)//当前已经走过的步数
{
for(int j=0;j<=x;j++)//已经走到了的地方
{
if(f[i-1][j])
{
if(j+a[i]<=x) f[i][j+a[i]]=1;
if(j+b[j]<=x) f[i][j+b[i]]=1;
}
}
}
if(f[n][x]) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}