[题解]CF864E Fire

#1.0 简单分析

01背包的变式。约束条件由空间变为了时间,这里要注意到时间的一个特殊的性质:具有顺序

首先,要进行一步很简单但很重要的步骤:排序

那么为什么要排序呢?

显然。题目中给的顺序并不是时间顺序,而对于所有物品,我们应当先考虑烧毁时间较早的物品,原因很简单:每拯救一个物品需要消耗一定的时间。假如我们先考虑在时段 \(0\sim t\) 拯救烧毁时间较后的物品 A,接着,我们在考虑烧毁时间较前的物品 B,但我们并不知道之前 A 物品具体是在什么时候拯救的,如果要枚举,显然数据量太大了。

假设我们有两个物品 A,B,A 比 B 先烧毁,那么如果我们先考虑 A 得到的结果,一定不会比先考虑 B 得到的结果差,毕竟我们可以通过一些手段放弃之前的选择,而且可以更好地记录每个物品选取的时间。

注意到,我们还需要输出路径,那么可以增设状态,保存前驱,然后递归地遍历。

设计状态

  • \(f_{i,j}\) 表示当前考虑到第 \(i\) 个物品,拯救出的最后一个物品的拯救结束时间为 \(j\) 的最大收益。
  • \(g_{i,j}\) —— 第 \(i-1\) 个物品时,拯救出的最后一个拯救结束时间为 \(g_{i,j}\)

状态转移: 可以直接按 01 背包进行转移。

还有一点要注意:

这里的答案并不像普通的 01 背包一般是 \(f_{n,T}\),而是 \(f_{n,1}\sim f_{n,T}\) 中的最大值,原因也很简单:我们设计的状态中的 \(j\)拯救出的最后一个物品的拯救结束时间,这个最后一个物品不一定是哪一个物品,自然会有不同的答案。

具体实现请见代码及注释。

#2.0 代码实现

const int N = 110;
const int M = 2010;
const int INF = 0x3fffffff;

struct T{
    int t,d,p;
    int ind;
};T a[N];

int n,f[N][M],g[N][M],maxn = -INF,ans = -INF;
int list[N],cnt,ans2;

inline int cmp(const T &x,const T &y){
    return x.d < y.d;
}

inline int Max(const int &x,const int &y){
    return x > y ? x : y;
}

inline void Path(int k,int t){ //递归遍历方案,并数清个数
    if (k <= 0) return;
    Path(k - 1,g[k][t]);
    if (f[k][t] != f[k - 1][t]) //判断这个物品是否被选——f[i] 与 f[i-1] 是否相等
      list[++ cnt] = k;
}

int main(){
    scanf("%d",&n);
    for (int i = 1;i <= n;i ++){
        scanf("%d%d%d",&a[i].t,&a[i].d,&a[i].p);
        a[i].ind = i; 
    }
    sort(a + 1,a + 1 + n,cmp); //排序
    for (int i = 1;i <= n;i ++){
        for (int j = 1;j <= 2000;j ++) //继承
          f[i][j] = f[i - 1][j],g[i][j] = j;
        for (int j = a[i].d - 1;j >= a[i].t;j --)
          if (f[i][j] < f[i - 1][j - a[i].t] + a[i].p){ //更新
              f[i][j] = f[i - 1][j - a[i].t] + a[i].p;
              g[i][j] = j - a[i].t;
          }  
    }
    for (int j = 1;j <= 2000;j ++) //找到最大答案
      if (f[n][j] > ans) ans = f[n][j],ans2 = j;
    Path(n,ans2); //统计
    printf("%d\n%d\n",ans,cnt);
    for (int i = 1;i <= cnt;i ++)
      printf("%d ",a[list[i]].ind);
    return 0;
}

END

希望能给您带来收获。

posted @ 2021-05-25 20:09  Dfkuaid  阅读(77)  评论(0编辑  收藏  举报