Codeforces Round #436 (Div. 2) 864E. Fire

那天晚上發現有場cf時間比較早就跑去打了一下,只寫出ABCDE的我(一次都沒被hack,也一次都沒去hack)……


地址:Codeforces Round #436 (Div. 2) 864E. Fire


題目:

E. Fire

time limit per test : 2 seconds
memory limit per test : 256 megabytes
input : standard input
output : standard output


Polycarp is in really serious trouble — his house is on fire! It’s time to save the most valuable items. Polycarp estimated that it would take ti seconds to save i-th item. In addition, for each item, he estimated the value of di — the moment after which the item i will be completely burned and will no longer be valuable for him at all. In particular, if ti ≥ di, then i-th item cannot be saved.

Given the values pi for each of the items, find a set of items that Polycarp can save such that the total value of this items is maximum possible. Polycarp saves the items one after another. For example, if he takes item a first, and then item b, then the item a will be saved in ta seconds, and the item b — in ta + tb seconds after fire started.


Input
The first line contains a single integer n (1 ≤ n ≤ 100) — the number of items in Polycarp’s house.

Each of the following n lines contains three integers ti, di, pi (1 ≤ ti ≤ 20, 1 ≤ di ≤ 2 000, 1 ≤ pi ≤ 20) — the time needed to save the item i, the time after which the item i will burn completely and the value of item i.


Output
In the first line print the maximum possible total value of the set of saved items. In the second line print one integer m — the number of items in the desired set. In the third line print m distinct integers — numbers of the saved items in the order Polycarp saves them. Items are 1-indexed in the same order in which they appear in the input. If there are several answers, print any of them.


Examples
input

3
3 7 4
2 6 5
3 7 6

output

11
2
2 3 

input

2
5 6 1
3 3 5

output

1
1
1 

Note
In the first example Polycarp will have time to save any two items, but in order to maximize the total value of the saved items, he must save the second and the third item. For example, he can firstly save the third item in 3 seconds, and then save the second item in another 2 seconds. Thus, the total value of the saved items will be 6 + 5 = 11.

In the second example Polycarp can save only the first item, since even if he immediately starts saving the second item, he can save it in 3 seconds, but this item will already be completely burned by this time.


題解:

至於題意什麼的怕誤導人…………google翻譯
算了還是講一下吧:
就是一個人家裏着火了,要搶救一些重要的東西,每件東西都有價值,搶救每一件東西也要花費一些時間,每件東西燃盡也需要時間(如果救出來的時候這個物品剛好燃盡的話,就不算就出來,參考樣例),而這些數值往往不相同(可能相同)。
問該人能搶救的最大價值,和搶救方案.
輸入:
第一行一個數 n 表示有 n 件物品待搶救。
之後 n 行,每行 3 個整數ti,di,pi(1ti20,1di2000,1pi20) 分別表示救出第 i 個物品所花的時間,這個物品燃盡的時間和這個物品的價值.
輸出:
第一行是一個整數表示最大價值。
第二行是一個整數表示救出物品數目。
第三行按照救出順序輸出救出物品的編號。


這道題的算法就是揹包了,之前練了下揹包所以比較敏感。
f[i][j] 表示現在第 i 個物品,時間已經到 j 秒時的最大價值。對於每個物品有兩種操作,就是拿與不拿,開個 bool 類來保存一下當前狀態是不是取了第 i 個物品。而且在每次 max 更新的時候記錄下是從上次那個狀態更新過來,這樣我們就可以直接從最後的物品來回溯到第一個物品,並且通過 bool 數組來獲取了哪些物品。
當然所有的物品讀入後還需要按 d 值從小到大排序,因爲每個物品的狀態都要從之前更早的時間更新而來,如果一個很早就燃盡的物品放到後面來更新的話,就沒法更新它燃盡之後的狀態了。


代碼:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

int f[105][2005];
int last[105][2005];
bool vis[105][2005];
int n,ans,mxt,num;
int sta[105],top;
struct node{
    int a,b,c,num;
}x[105];

bool cmp(node a,node b){
    return a.b < b.b;
}

int main(){
    n = read();
    for(int i = 1;i <= n;i++){
        x[i].a = read(); x[i].b = read(); x[i].c = read();
        x[i].num = i;
        mxt = max(mxt,x[i].b);
    }
    sort(x+1,x+n+1,cmp);
    for(int i = 1;i <= n;i++){
        for(int j = x[i].a;j < x[i].b;j++){
            if(f[i][j] <= f[i-1][j-x[i].a]+x[i].c){
                f[i][j] = f[i-1][j-x[i].a]+x[i].c;
                last[i][j] = j-x[i].a;
                vis[i][j] = true;
            }
        }
        for(int j = 0;j < mxt;j++){
            if(f[i][j] <= f[i-1][j]){
                f[i][j] = f[i-1][j];
                last[i][j] = j;
                vis[i][j] = false;
            }
        }
    }
    for(int i = 0;i < mxt;i++){
        if(ans < f[n][i]){
            ans = f[n][i];
            num = i;
        }
    }
    printf("%d\n",ans);
    for(int i = n;i >= 1;i--){
        if(vis[i][num]){
            sta[++top] = x[i].num;
        }
        num = last[i][num];
    }
    printf("%d\n",top);
    while(top > 0){
        printf("%d ",sta[top]);
        top--;
    }
    printf("\n");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章