E. Fire -01背包+路径输出

今晚边吃烤鸡边打练习赛,导致这道简单的dp题没做出来,我辜负了教练,辜负了队友。在此自罚一篇博客。

一、题目

传送门

二、分析

v保存该物品的时间,w该物品的价值,t该物品在上面时候毁坏。

定义dp数组:

dp[i]:在前i秒内能能保存的物品最大总和

状态注意方程:

dp[j] = max(dp[j],dp[j-v]+w);   j<t且j-v>=0

三、错误过程

WA第一版

#include<bits/stdc++.h>
using namespace std;
const int N=110;
const int M=2010;

int dp[M];
int w[N],v[N],t[N];
int n,m;
int g[N][M];
int cnt;
int q[N],idx;

void dfs(int i,int j)
{
	if(i<=0)
		return ;
    if(g[i][j])
    {
        cnt++;
        q[idx++]=i;
        dfs(i-1,j-v[i]);
    }
    else
        dfs(i-1,j);
}

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d",&v[i],&t[i],&w[i]);
        m=max(m,t[i]);
    }

    for(int i=1;i<=n;i++)
    {
        for(int j=t[i];j>=v[i];j--)
        {
            if(dp[j]<dp[j-v[i]]+w[i])
            {
                dp[j]=dp[j-v[i]]+w[i];
                g[i][j]=1;
            }
        }
    }

	
    dfs(n,m);
    cout<<dp[m]<<endl;
    cout<<cnt<<endl;
    for(int i=idx-1;i>=0;i--)
        cout<<q[i]<<' ';
    
    return 0;
}

没有考虑第i个物品存在时间小于第i-1的情况,并且读题没发现j<t,而不是j<=t

WA第二版

#include<bits/stdc++.h>
using namespace std;
const int N=110;
const int M=2010;

int dp[M];
int n,m;
int g[N][M];
int cnt;
int q[N],idx;

struct node
{
	int id;
    int w,v,t;
}e[N];

bool cmp(struct node x1,struct node x2)
{
    return x1.t<x2.t;
}


void prin()
{
	for(int i=0;i<M;i++)
		cout<<dp[i]<<" ";
	cout<<endl;
}

void dfs(int i,int j)
{
	if(i<=0)
		return ;
    if(g[i][j])
    {
        cnt++;
        q[idx++]=e[i].id;
        dfs(i-1,j-e[i].v);
    }
    else
        dfs(i-1,j);
}

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d",&e[i].v,&e[i].t,&e[i].w);
        e[i].id=i;
    }

    sort(e+1,e+1+n,cmp);

    for(int i=1;i<=n;i++)
    {
        for(int j=e[i].t-1;j>=e[i].v;j--)
        {
            if(dp[j]<dp[j-e[i].v]+e[i].w)
            {
                dp[j]=dp[j-e[i].v]+e[i].w;
                g[i][j]=1;
            }
        }
        
    }

    dfs(n,e[n].t-1);
    cout<<dp[e[n].t-1]<<endl;
    cout<<cnt<<endl;
    for(int i=idx-1;i>=0;i--)
        cout<<q[i]<<' ';
     
    return 0;
}

没有考虑第i个物品存在时间特别长,第i-1存在时间特别短,误认为dp[n][e[n].t-1]一定为答案

四、正确代码

#include<bits/stdc++.h>
using namespace std;
const int N=110;
const int M=2010;

int dp[M];
int n,m;
int g[N][M];
int cnt;
int q[N],idx;

struct node
{
	int id;
    int w,v,t;
}e[N];

bool cmp(struct node x1,struct node x2)
{
    return x1.t<x2.t;
}


void prin()
{
	for(int i=0;i<M;i++)
		cout<<dp[i]<<" ";
	cout<<endl;
}

void dfs(int i,int j)
{
	if(i<=0)
		return ;
    if(g[i][j])
    {
        cnt++;
        q[idx++]=e[i].id;
        dfs(i-1,j-e[i].v);
    }
    else
        dfs(i-1,j);
}

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d",&e[i].v,&e[i].t,&e[i].w);
        e[i].id=i;
    }

    sort(e+1,e+1+n,cmp);
	
	int x,y,Max=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=e[i].t-1;j>=e[i].v;j--)
        {
            if(dp[j]<dp[j-e[i].v]+e[i].w)
            {
                dp[j]=dp[j-e[i].v]+e[i].w;
                g[i][j]=1;
            }
            if(Max<dp[j])
            {
            	Max=dp[j];
            	x=i,y=j;
			}
        }
        
    }

    dfs(x,y);
    cout<<Max<<endl;
    cout<<cnt<<endl;
    for(int i=idx-1;i>=0;i--)
        cout<<q[i]<<' ';
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值