洛谷 P1941 飞扬的小鸟 (NOIP 2014)

题面

题解

背包细节题,wa了一片,上升的过程我们可以看做一个完全背包(多重背包好像跑不过去),下降
过程是一个0/1背包,为了避免冲突应该先跑多重,先跑0/1就有可能产生这个点又上升又下降的
非法情况,最后在将非法情况删去。

代码

#include<bits/stdc++.h>

using namespace std;
const int MAXM = 1005;
const int MAXN = 10005;
const int inf = 0x3f3f3f3f;

inline int rd(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0' && ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return x*f;
}

int dp[MAXN][MAXM],px[MAXN],py[MAXN];
int n,m,k,ans=inf;
int x[MAXN],y[MAXN];

int main(){
    memset(dp,0x3f,sizeof(dp));
    n=rd();m=rd();k=rd();
    for(register int i=1;i<=n;i++) x[i]=rd(),y[i]=rd(),py[i]=inf;
    for(register int i=1;i<=k;i++) {
        int where;where=rd();
        px[where]=rd();py[where]=rd();
    }
    for(register int i=1;i<=m;i++) dp[0][i]=0;
    for(register int i=1;i<=n;i++){
        for(register int j=x[i];j<=m;j++){
            if(j==m)
                for(register int o=m-x[i];o<=m;o++){
                    dp[i][j]=min(dp[i][j],dp[i-1][o]+1);
                    dp[i][j]=min(dp[i][j],dp[i][o]+1);
                }
            dp[i][j]=min(dp[i][j],dp[i-1][j-x[i]]+1);
            dp[i][j]=min(dp[i][j],dp[i][j-x[i]]+1);
        }
        int l=max(px[i]+1,1);int r=min(py[i]-1,m-y[i]);
        for(register int j=l;j<=r;j++)
            dp[i][j]=min(dp[i][j],dp[i-1][j+y[i]]);
        for(register int j=px[i];j;j--) dp[i][j]=inf;
        for(register int j=py[i];j<=m;j++) dp[i][j]=inf;
    }   
//  for(register int i=1;i<=n;i++){
//      cout<<i;
//      for(register int j=1;j<=m;j++)
//          cout<<"     "<<j<<" "<<dp[i][j]<<endl;
//      cout<<endl;
//  }
    for(register int i=1;i<=m;i++) ans=min(dp[n][i],ans);
    if(ans!=inf){
        puts("1");
        printf("%d",ans);
    }
    else{
        ans=0;
        puts("0");
        for(register int i=1;i<=n;i++){
            bool flag=false;
            for(register int j=1;j<=m;j++)
                if(dp[i][j]!=inf){
                    flag=1;
                    if(py[i]!=inf){
                        ans++;
                        break;
                    }
                }
            if(!flag) break;
        }
        printf("%d",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/sdfzsyq/p/9677019.html