CodeForces 864E Fire (记录路径的01背包)

题目链接:http://codeforces.com/problemset/problem/864/E

题目分析

 这个题目也是比较明显的01背包了,我们只需要考虑是否选择某一物品即可,把时间 t [ i ] 当作重量,p [ i ] 当作价值, d [ i ] 当作最大枚举重量即可,不过,我们平时是从最大重量(一般为总重)开始向前枚举背包容量,在这里,我们为了使某一物品选择具有合法性,所以我们从 d [ i ] - 1 开始向前枚举容量。

然后就是重点的最优路径记录了,在这里我们用vector数组记录价值为 j 的时候的最优路径,那么很明显,我们在价值为 j 的时候,如果满足转移方程  dp[j] < dp[ j - things[i].t ] + things[i].p ,那么我们得到时间(容量)为 j 的情况下的最优解,是由时间(容量)为 j - things[i].t的时候转移而来,那么这个时候的最优路径很明显就是在 j - things[i].t 基础上加上了当前位置物品 things[i].id 得到的 ,这样我们就得到了每一个时间下的最优路径。

最后,我们枚举每一个时间(容量),找到最大价值对应的时间(容量),并输出在这个时间(容量)得到最大价值的路径即可。

(注意判断一下没有选择任何物品的情况,就像我因此RE了,还有就是枚举物品的时候要按照烧毁时间从小到大枚举,这个很好懂吧)

代码区

#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int Max = 3e3 + 10;

typedef struct Object {
	int t;		//耗费时间
	int d;		//烧毁时间
	int p;		//价值
	int id;		//物品编号
	bool operator<(const Object& o)const
	{
		return this->d < o.d;
	}
}Object;

Object things[Max];		//记录物品
vectorpath[Max];	//path[j] 记录时间(容量)为j的时候的最优路径
int dp[Max];			//dp[j]   记录容量为j的时候的最大价值

int main()
{
	std::ios::sync_with_stdio(false);
	int n;
	while (cin >> n)
	{
		memset(dp, 0, sizeof(dp));

		int  m = 0;
		for (int i = 1; i <= n; i++)
		{
			cin >> things[i].t >> things[i].d >> things[i].p;
			things[i].id = i;
			m = max(m, things[i].d);	//记录完全烧毁的时间,也就是最大容量
		}
		sort(things + 1, things + 1 + n);

		for (int i = 1; i <= m;i++)	//清空上一次遗留的路径
		{
			path[i].clear();
		}

		for (int i = 1; i <= n; i++)
		{
			for (int j = things[i].d - 1; j >= things[i].t;j--)
			{
				if (dp[j] < dp[j - things[i].t] + things[i].p)
				{
					dp[j] = dp[j - things[i].t] + things[i].p;
					path[j] = path[j - things[i].t];			//记录路径关键步骤,path[j - things[i].t]表示转移前的最优路径
					path[j].push_back(things[i].id);			//存入当前物品
				}
			}
		}
		int id = -1;		//最大价值时候的时间
		int sum = -1;		//最大价值

		for (int i = 0; i <= m; i++)
		{
			if (dp[i] > sum)
			{
				sum = dp[i];
				id = i;
			}
		}
		cout << sum << endl;
		cout << path[id].size() << endl;

		if (path[id].size() != 0)	//这个是否存在还需要判定一下是否存在最优路径,不然就像我不知道怎么回事RE了
		{
			cout << path[id][0];
			for (int i = 1; i < path[id].size();i++)
			{
				cout << " " << path[id][i];
			}
			cout << endl;
		}

	}
	return 0;
}

 

你可能感兴趣的:(DP)