这个问题其实用贪心策略更好吧,硬要用动态规划也是没有问题的。
/*
* 现在一个房子里着火了,你需要从这个房里抢救一些东西出来。
* 有n件物品,第i件物品的价值是p[i],抢救需要花费t[i]的时间,
* 如果物品超过d[i]的时间还没有被抢救出来就会被烧掉。
* 问能救出的物品价值之和最大为多少,并且输出你能抢到的物品编号。
* 这个问题看起来和活动选择问题很像,区别是这个问题的起始时间都是0。
* 设f[i][j]表示考虑到第i个物品,到j时刻为止最大能救的价值量。
* 如果不选择物品,则f[i][j]=f[i-1][j]。
* 如果选择第i件物品,那么在第i-1件物品考虑完后的时刻+t[i]=j,且j<=d[i],所以第i-1件物品考虑完后的时刻为j-t[i]
* 所以f[j]=max(f[i-1][j],f[i-1][j-t[i]]+p[i],且t[i]<=j<=d[i])。
* 这里需要以截止时间d[i]为关键字进行升序排序。(这里是一个贪心的策略,优先救取会先被烧掉的东西,这样有更多的机会去救别的东西)
*/
#include<iostream>
#include<vector>
#include<iomanip>
#include<algorithm>
using namespace std;
#define example 0
class thing
{
private:
char ID;//物品编号
int P;//物品价值
int T;//物品抢救所花时间
int D;//物品被烧毁的时刻
public:
thing(char _ID, int _P, int _T, int _D) :ID(_ID), P(_P), T(_T), D(_D) {}
thing(const thing& another) :ID(another.ID), P(another.P), T(another.T), D(another.D) {}
inline char id() { return ID; }
inline int p() { return P; }
inline int d() { return D; }
inline int t() { return T; }
~thing(){}
friend bool operator<(const thing& a, const thing& b) { return a.D < b.D; }
};
#if example==0
vector<thing> a = {
{'A',4,3,7},
{'B',5,2,6},
{'C',6,3,7 }
};
#elif example==1
vector<thing>a = {
{'A',1,5,6},
{'B',5,3,3}
};
#endif
void show(int** r,int i, int j);
int main()
{
sort(a.begin(), a.end(), [](const thing& a, const thing& b) {return a < b; });
int TIME = (a.end() - 1)->d();//取最长被烧毁时刻
int N = a.size();
int** f = new int* [N+1];
int** Rec = new int* [N + 1];
for (int i = 0; i <= N; i++)
{
f[i] = new int[TIME + 1]{ 0 };
Rec[i] = new int[TIME + 1]{ 0 };
}
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= TIME; j++)
{
if (j > a[i - 1].d())//所剩时间不够救出第i件物品,只能放弃
f[i][j] = f[i - 1][j];
else if (j < a[i - 1].t())//大火还没烧,没开始抢救
{
f[i][j] = f[i][j - 1];
Rec[i][j] = Rec[i][j - 1];
}
else
{
if (f[i - 1][j - a[i - 1].t()] + a[i - 1].p() > f[i - 1][j])
{
f[i][j] = f[i - 1][j - a[i - 1].t()] + a[i - 1].p();
Rec[i][j] = 1;
}
else
f[i][j] = f[i - 1][j];
}
}
}
cout<<"抢救最大价值为: " << f[N][TIME] << endl;
show(Rec, N, TIME);
for (int i = 0; i <= N; i++)
{
delete[] f[i];
delete[] Rec[i];
}
delete[] f;
delete[] Rec;
return 0;
}
void show(int** r,int i, int j)
{
if (i == 0)
return;
show(r, i - 1, j - r[i][j] * a[i-1].t());
if (r[i][j] != 0)
cout << "选取了" << a[i - 1].id() << endl;
}