codevs 3325 过山车 DP

题目

codevs 3325 过山车

题解

和裸的线段覆盖差不多,但是我数组开小了还是没能1A。dp[ i ][ j ]表示覆盖到i的长度,用了j的代价获得的最大快乐值。先把物品按右端点排序之后,依次扫描有没有可以用来转移的物品。也就是说如果存在一个物品m使得m.x+m.len==i(右端点在i),那么:

dp[ i ][ j ]=max(dp[ i ][ j ],dp[ m.x ][ j-m.cost ]+m.val );

(注意dp时两个for和一个while的顺序)因为强制要求覆盖满,所以初始状态只能是dp[ 0 ][ 0 ]=0, 别的都为-1,也是因为这个所以答案不一定是dp[m][C](m是长度,C是最大的代价),需要扫一遍。

代码

//QWsin
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxl=1000+10;
const int maxn=10000+10;
const int maxm=1000+10;

inline int read()
{
    int ret=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) ret=ret*10+ch-'0';
    return ret;
}

struct equip{
    int x,len,val,cost;
    bool operator < (const equip &rhs)const{
        return x+len<rhs.x+rhs.len;
    }
    inline void input(){
        x=read();len=read();val=read();cost=read();
    }
}a[maxn];

int dp[maxl][maxm];

int main()
{
    freopen("std.in","r",stdin);
    int m,n,C;cin>>m>>n>>C;
    for(int i=1;i<=n;i++) a[i].input();
    memset(dp,-1,sizeof(dp));
    dp[0][0]=0;
    sort(a+1,a+n+1);
    int p=0;
    for(int i=1;i<=n;i++)
        while(p+1<=n&&a[p+1].x+a[p+1].len==i)
        {
            p++;
            for(int j=C;j>=a[p].cost;j--)
                if(dp[a[p].x][j-a[p].cost]!=-1)
                    dp[i][j]=max(dp[i][j],dp[a[p].x][j-a[p].cost]+a[p].val);
        }
    int ans=-1;
    for(int j=1;j<=C;j++) ans=max(ans,dp[m][j]);    
    printf("%d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值