CF864 E DP 输出路径

n个物品有Deadline,拿物品需要花费时间,问取得最大价值的方案。

本质是个01背包,先按时间排序,然后把花费的时间作为背包就行了。

主要就是找方案,倒过来找发生转移的就行了。

太菜了真的不会打CF,每次都要掉分

/** @Date    : 2017-09-25 22:28:30
  * @FileName: E.cpp
  * @Platform: Windows
  * @Author  : Lweleth (SoungEarlf@gmail.com)
  * @Link    : https://github.com/
  * @Version : $Id$
  */
#include <bits/stdc++.h>
#define LL long long
#define PII pair<int ,int>
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 2e5+20;
const double eps = 1e-8;

int n;
int dp[110][3000];
struct yuu
{
	int v, c, d, idx;
}a[200];

int cmp(yuu a, yuu b)
{
	if(a.d != b.d)
		return a.d < b.d;
	return a.c < b.c;
}
int main()
{
	cin >> n;
	int sum = 0;
	for(int i = 1; i <= n; i++)
	{
		scanf("%d%d%d", &a[i].c, &a[i].d, &a[i].v), a[i].idx = i;
		sum += a[i].c;
	}
	sort(a + 1, a + n + 1, cmp);
	MMF(dp);
	int ma = 0;
	int pos = 0;
	for(int i = 1; i <= n; i++)
	{
		for(int j = 0; j <= sum; j++)
		{
			if(j < a[i].d && j >= a[i].c)
				dp[i][j] = max(dp[i - 1][j - a[i].c] + a[i].v, dp[i - 1][j]);
			else dp[i][j] = dp[i - 1][j];
			if(ma < dp[i][j])
				pos = j, ma = dp[i][j];
		}
	}
	vector<int>q;
	for(int i = n; i >= 1; i--)
	{
		if(pos > a[i].d || pos < a[i].c || dp[i - 1][pos] >= dp[i - 1][pos - a[i].c] + a[i].v)
			continue;
		pos -= a[i].c;
		q.PB(i);
	}
	reverse(q.begin(), q.end());
	printf("%d\n", ma);
	printf("%d\n", q.size());
	for(auto i : q)
		printf("%d ", a[i].idx);
	printf("\n");
    return 0;
}
posted @ 2017-09-25 23:25  Lweleth  阅读(268)  评论(0编辑  收藏  举报