[Luogu] P1899 Magic Item

Luogu P1899 Magic Item


Topic description:

There are two types of items: normal items and magic items. Normal items have no magical properties, while magic items have some magical properties. Every normal item has a value \(P\) , but every magic item has two values: a pre-identification value \(P_{1}\) and a post-identification value \(P_{2}\) (of course , \(P_{1}\) is always greater than \(P_{2}\) ).

In order to identify a magic item, you need to purchase a magic scroll and use it to identify the magic item. After identifying a magic item, the identification scroll disappears. Each appraisal scroll costs \(S\) dollars, if you don't have enough money, you will not be able to buy any magic scrolls.

Right now, you are in a bazaar and have a lot of items at the same time. You know the value of each item and want to sell them all. So, what is the most you can earn?

You can assume:

  • You start with no money.
  • All magic items have not been identified.
  • As long as you have enough money, you can buy as many magic scrolls as you want.

Input and output format:

Input format (magic.in):

The first line has two integers \(N\) and \(S\) ( \(0 < S \leqslant 10000\) ), which represent the number of items you have and the price of an appraisal scroll.

Next \(N\) lines, each giving the price of an item.

For each common item, there is only one integer \(P\) on that line ( \(0 < P \leqslant 10000\) ).

For each common item, that line will have two integers \(P_{1}\) and \(P_{2}\) ( \(0 < P_{1} < P_{2} \leqslant 10000\) ).

Output format (magic.out):

An integer representing the maximum amount of money you can earn.

Example:

Input #1:

2 10
10
20 100

Output #1:

100

Data size:

\(N \leqslant 50\) for 30% of the data ;

For 100% data, \(N \leqslant 1000\) .

portal

answer:

Consider first the processing of input. Obviously, when dealing with ordinary items, you can directly choose to sell them as the cost of buying scrolls. Next, consider magic items. When the \(P_{2}\) minus \(S\) of the magic item is not greater than \(P_{1}\) , it is also solddefinitely oneOK. Thus, we will only save \(P_{2} - S \geqslant P_{1}\) magic items.

Next, deal with magic items. (For convenience of expression, let \(ans\) be the money in hand after selling all sellable items, \(P_{i,1}, P_{i, 2}\) represent the \(i\) th waiting \(P_{1}, P_{2}\) for dealing with magic items , \(tot\) for all items \(P_{1}\) ).

  1. The first is when \(ans \geqslant S\) . Because all pending items \(i\) satisfy \(P_{i, 2} - S \geqslant P_{i, 1}\) , so, first buy a magic scroll, identify and sell the first magic After buying the item, the value of \(ans\) must be greater than before buying the scroll. So directly identify all unprocessed magic items, and then sell them at the magic price.
  2. Second is when \(ans < S\) . We need to sell some magic items to make \(ans \geqslant S\) , then we can deal with the previous case. At this time, you need to run a DP to calculate which (which) is better to sell. Available \(P_{i, 2} - S - P_{i, 1}\) is the loss of the \(i\) th item, the transfer equation: \(F[j] = min(F[j], f[j - P_{i, 1}] + (P_{i, 2} - S - P_{i, 1}))\) (where \(F[j]\) is not counted \(ans\) Including, and then get \(j\) element when generating the minimum loss and). Run DP to calculate the minimum loss (set to \(minn\) ) ( \(S - ans \leqslant j \leqslant tot\) ). If you can make up the money to use \(ans \geqslant S\) , then deal with the situation according to the situation, and then \(ans - minn\) ; if not, it means that a magic scroll can't be bought, directly output \ (tot\) is enough.

Another: If you just write it according to the second case, the time complexity will be out of the pot ( \(N * tot \leqslant 1e^{10}\) ); so you need to optimize the DP a little bit: let \(F[j]\) Represents the smallest sum of costs when the money \(\geqslant j\) is obtained. Transition equation: \(F[j] = min(f[j], f[max(j - P_{i, 1}, 0)] +(P_{i, 2} - S - P_{i, 1} ))\) . ( \(N * S \leqslant 5e^{6}\) )

Code:

#include <cstdio>
const int INF = 999999999;
const int MAXP = 5000;
int n, s, top, ans, tmp, tmp2, tmp3, tot, xxx;
int p[1010], o[1010], f[5001];
char c(0);
inline int min(int a, int b) {
    return (a < b ? a : b);
}
inline int max(int a, int b) {
    return (a > b ? a : b);
}
int main() {
    scanf("%d%d", &n, &s);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &tmp);
        tot = tot + tmp;
        scanf("%c", &c);
        if(c == ' ') {
            scanf("%d", &tmp2);
            if(tmp2 - s > tmp) {
                p[++top] = tmp2;
                o[top] = tmp;
            }
            else ans = ans + tmp;
        } else {ans = ans + tmp;}
    }
    xxx = ans;                          //存储ans的值,因为下一步要对ans进行操作
    for (int i = 1; i <= top; ++i)      //按情况一处理
        ans = ans + p[i] - s; 
    if(xxx < s){                        //如果为情况二
        tmp3 = min(MAXP, tot);  //因为f[j]代表了大于等于j的最小值,所以DP跑到卷轴价格的最大值5000即可
        for (int i = 1; i <= tmp3; ++i) f[i] = INF;
        for (int i = 1; i <= top; ++i) {
            tmp = o[i]; tmp2 = p[i] - s - tmp; 
            for (int j = tmp3; j >= 1; j--)
                f[j] = min(f[j], f[max(j - tmp, 0)] + tmp2);    //取max(j-tmp,0)以免得负值
            }
        int minn(INF);
        for (int i = s - xxx; i <= tmp3; ++i)           //取最小代价和
            minn = min(minn, f[i]);
        if(minn < INF) printf("%d\n", ans - minn);      //
        else printf("%d\n", tot);
    } else {printf("%d\n", ans); return 0;}
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325020660&siteId=291194637