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;
}
posted @ 2022-09-14 16:56  Vijurria  阅读(95)  评论(0编辑  收藏  举报