hdu 4502(dp)

刚开始做,想到的方法是,按照时间顺序,从小到大,排完序之后,在节点i处的最大值一定在满足条件的节点j后。

满足的条件是:第j个节点结束时间小于i节点的开始时间。

那么j可以为1<=j<i;

即  dp[i]=max(dp[i],dp[j])+c[i]     (1<=j<i)

#include <iostream>
#include<algorithm>
using namespace std;

struct work
{
	long s,e,c;
}w[1005];

int cmp(work w1,work w2)
{
	if(w1.s==w2.s&&w1.e==w2.e)
		return w1.c>=w2.c;
	if(w1.s==w2.s)
		return w1.e<w2.e;
	return w1.s<w2.s;
}

int main()
{
//	freopen("in.txt","r",stdin);
	int t;
	int m,n;
	int dp[1005];
	int k=0;
	long a,b,c;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d %d",&m,&n);
		k=1;
		for(int i=1;i<=n;i++)
		{
			scanf("%ld %ld %ld",&a,&b,&c);
			if(a>=1&&b<=m) 
			{		w[k].s=a; w[k].e=b; w[k].c=c;   k++;  }
		}
		sort(w+1,w+k,cmp);
		for(int i=1;i<k;i++)
			dp[i]=0;
		if(w[1].s<=m&&w[1].e<=m)
			dp[1]=w[1].c;
		for(int i=2;i<k;i++)
		{
			for(int j=1;j<i;j++)      //从1开始到i-1遍历,只要w[j].e<w[i].s,说明i可以跟在j的后面
				if(w[j].e<w[i].s&&dp[j]>dp[i])  //找到最大值
					dp[i]=dp[j];
			dp[i]+=w[i].c;        //加上本身的值
		}
		long max_c=0;
		for(int i=1;i<k;i++)    //所有的节点搜完最大值之后,最大值并不一定在dp[k-1]中
			if(dp[i]>max_c)
				max_c=dp[i];
		printf("%ld\n",max_c);
	}	
	return 0;
}


后来,看了下discuss。看到了01背包的做法。

dp[i][j]=max(dp[i-1][j],dp[i][s[i]-1]+c[i])   j>=e[i];


#include <iostream>
#include<algorithm>
using namespace std;

struct work
{
	long s,e,c;
}w[1005];

int cmp(work w1,work w2)
{
	if(w1.s==w2.s&&w1.e==w2.e)
		return w1.c>=w2.c;
	if(w1.s==w2.s)
		return w1.e<w2.e;
	return w1.s<w2.s;
}

int max(int a,int b)
{
	return a>b?a:b;
}

int main()
{
//	freopen("in.txt","r",stdin);
	int t;
	int m,n;
	int dp[110];
	int k=0;
	long a,b,c;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d %d",&m,&n);
		k=1;
		for(int i=1;i<=n;i++)
		{
			scanf("%ld %ld %ld",&a,&b,&c);
			if(a>=1&&b<=m) 
			{		w[k].s=a; w[k].e=b; w[k].c=c;   k++;  }
		}
		sort(w+1,w+k,cmp);
		for(int i=0;i<=m;i++)
			dp[i]=0;
		for(int i=1;i<k;i++)
			for(int j=m;j>=w[i].e;j--)
				dp[j]=max(dp[j],dp[w[i].s-1]+w[i].c);
		printf("%d\n",dp[m]);
	}
	return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值