LOJ P2500 [NOIP2014] 飞扬的小鸟【背包DP】

好吧我也是一个智障了最开始完全没有思路重新读题发现题目读漏了一个条件:每个单位时间可以点击多次屏幕,也就意味着你可以从 ( x , y ) 跳到多个 ( x + 1 , y i ) ,那么不就是背包了么。

D P ( I , J ) 表示跳到坐标 ( I , J ) 的最少步数,对于 i ,我们可以先假设 i 处没有障碍,那么背包处理所有点,然后再把实际有障碍的点全部赋值为 I n f

统计答案么也好统计,横坐标从后往前枚举直到某 D P ( I , J ) < I n f ,然后再从前往后统计障碍的个数就可以了。

参考代码:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define SG string
#define DB double
using namespace std;
const int Inf=1e8;
const int Max=1e4+5,Mx=2e3+5;
struct Coor{
    int X,Y;
}Act[Max];
struct Node{
    int Down,Up;
}Mov[Max];
int N,M,P,Ans,Jud[Max],DP[Max][Mx];
inline int Read(){
    int X=0;char CH=getchar();bool F=0;
    while(CH>'9'||CH<'0'){if(CH=='-')F=1;CH=getchar();}
    while(CH>='0'&&CH<='9'){X=(X<<1)+(X<<3)+CH-'0';CH=getchar();}
    return F?-X:X;
}
inline void Write(int X){
    if(X<0)X=-X,putchar('-');
    if(X>9)Write(X/10);
    putchar(X%10+48);
}
int main(){
    int I,J,K;
    N=Read(),M=Read(),P=Read();
    for(I=1;I<=N;I++){
        Mov[I].Up=M,Mov[I].Down=1;
        Act[I].X=Read(),Act[I].Y=Read();
    }
    for(I=1;I<=P;I++){
        int A=Read(),B=Read(),C=Read();
        Jud[A]=1;
        Mov[A].Up=C-1;
        Mov[A].Down=B+1;
    }
    memset(DP,0x3f3f,sizeof(DP));
    for(I=1;I<=M;I++){
        DP[0][I]=0;
    }
    for(I=1;I<=N;I++){
        for(J=Act[I].X+1;J<=M+Act[I].X;J++){
            DP[I][J]=min(DP[I-1][J-Act[I].X]+1,DP[I][J-Act[I].X]+1);
        }
        for(J=M+1;J<=M+Act[I].X;J++){
            DP[I][M]=min(DP[I][M],DP[I][J]);
        }
        for(J=1;J<=M-Act[I].Y;J++){
            DP[I][J]=min(DP[I][J],DP[I-1][J+Act[I].Y]);
        }
        for(J=1;J<Mov[I].Down;J++){
            DP[I][J]=Inf;
        }
        for(J=Mov[I].Up+1;J<=M;J++){
            DP[I][J]=Inf;
        }
    }
    Ans=Inf;
    for(I=1;I<=M;I++){
        Ans=min(Ans,DP[N][I]);
    }
    if(Ans!=Inf){
        puts("1"),Write(Ans);
    } else {
        for(I=N;I;I--){
            for(J=1;J<=M;J++){
                if(DP[I][J]<Inf){
                    break;
                }
            }
            if(J<=M){
                break;
            }
        }int Cnt=0;
        for(J=1;J<=I;J++){
            if(Jud[J]==1){
                Cnt++;
            }
        }
        puts("0"),Write(Cnt);
    }
    return 0; 
}

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/81079289