UVa 812 - Trade on Verweggistan 解题报告(枚举)

56 篇文章 0 订阅

  Trade on Verweggistan 

Since the days of Peter Stuyvesant and Abel Tasman, Dutch merchants have been traveling all over the world to buy and sell goods. Once there was some trade on Verweggistan, but it ended after a short time. After reading this story you will understand why.

At that time Verweggistan was quite popular, because it was the only place in the world where people knew how to make a `prul'. The end of the trade on Verweggistan meant the end of the trade in pruls (or `prullen', as the Dutch plural said), and very few people nowadays know what a prul actually is.

Pruls were manufactured in workyards. Whenever a prul was finished it was packed in a box, which was then placed on top of the pile of previously produced pruls. On the side of each box the price was written. The price depended on the time it took to manufacture the prul. If all went well, a prul would cost one or two florins, but on a bad day the price could easily rise to 15 florins or more. This had nothing to do with quality; all pruls had the same value.

In those days pruls sold for 10 florins each in Holland. Transportation costs were negligible since the pruls were taken as extra on ships that would sail anyway. When a Dutch merchant went to Verweggistan, he had a clear purpose: buy pruls, sell them in Holland, and maximize his profits. Unfortunately, the Verweggistan way of trading pruls made this more complicated than one would think.

One would expect that merchants would simply buy the cheapest pruls, and the pruls that cost more than 10 florins would remain unsold. Unfortunately, all workyards on Verweggistan sold their pruls in a particular order. The box on top of the pile was sold first, then the second one from the top, and so on. So even if the fifth box from the top was the cheapest one, a merchant would have to buy the other four boxes above to obtain it.


As you can imagine, this made it quite difficult for the merchants to maximize their profits by buying the right set of pruls. Not having computers to help with optimization, they quickly lost interest in trading pruls at all.

In this problem, you are given the description of several workyard piles. You have to calculate the maximum profit a merchant can obtain by buying pruls from the piles according to the restrictions given above. In addition, you have to determine the number of pruls he has to buy to achieve this profit.

Input 

The input describes several test cases. The first line of input for each test case contains a single integer  w , the number of workyards in the test case (   1$ \le$w$ \le$50 ).

This is followed by w lines, each describing a pile of pruls. The first number in each line is the number b of boxes in the pile (0$ \le$b$ \le$20). Following it are b positive integers, indicating the prices (in florins) of the pruls in the stack, given from top to bottom.

The input is terminated by a description starting with w = 0. This description should not be processed.

Output 

For each test case, print the case number (1, 2, ...). Then print two lines, the first containing the maximum profit the merchant can achieve. The second line should specify the number of pruls the merchant has to buy to obtain this profit. If this number is not uniquely determined, print the possible values in increasing order. If there are more than ten possible values, print only the 10 smallest.

Display a blank line between test cases.

Sample Input 

1
6 12 3 10 7 16 5
2
5 7 3 11 9 10
9 1 2 3 4 10 16 10 4 16
0

Sample Output 

Workyards 1
Maximum profit is 8.
Number of pruls to buy: 4

Workyards 2
Maximum profit is 40.
Number of pruls to buy: 6 7 8 9 10 12 13

    解题报告:题意有些不好理解,大致是这样的。商人买货物,货物分成一堆一堆的。买某堆的时候必须从头开始买,如果想买第三个,那么第一个和第二个必须买。卖的价格都是10块,问最大利润,以及要达到最大利润货物的数量。数量可能有很多种,打印前10个最小的。

    最大利润很好求。每组求出最大的∑(a[i]), 0 <= i <= b,加起来就是最大的利润。而数量呢,每组选择到最大利润的数量可能有几种,枚举每种数量,和之前累积的数量加起来,取10个最小的就好了。这里用set实现,比较方便。另外使用了C++ 11 新特性,简易版的枚举容器类。代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <iomanip>
using namespace std;
#define ff(i, n) for(int i=0;i<(n);i++)
#define fff(i, n, m) for(int i=(n);i<=(m);i++)
#define dff(i, n, m) for(int i=(n);i>=(m);i--)
#define bit(n) (1LL<<(n))
typedef long long LL;
typedef unsigned long long ULL;
void work();
int main()
{
#ifdef ACM
    freopen("in.txt", "r", stdin);
#endif // ACM
    work();
}

/***************************************************/

typedef vector<int> vint;

void work()
{
    int n;
    bool first = true;
    int cas = 1;
    while(scanf("%d", &n) == 1 && n)
    {
        if(first)
            first = false;
        else
            puts("");

        int ans = 0;
        vector<vint> per;

        ff(i, n)
        {
            int b;
            scanf("%d", &b);

            int maxP = 0;
            int sum = 0;
            vint price;

            ff(j, b)
            {
                int tmp;
                scanf("%d", &tmp);
                price.push_back(tmp);

                sum += 10 - tmp;
                maxP = max(maxP, sum);
            }

            sum = 0;
            vint pos;
            if(maxP == 0) pos.push_back(0);
            ff(j, b)
            {
                sum += 10 - price[j];
                if(sum == maxP)
                pos.push_back(j+1);
            }

            ans += maxP;
            if(pos.size()) per.push_back(pos);
        }

        printf("Workyards %d\n", cas++);
        printf("Maximum profit is %d.\n", ans);
        printf("Number of pruls to buy:");

        int now = 1, pre = 0;
        set<int> ss[2];
        ss[now].insert(0);

        ff(i, per.size())
        {
            swap(now, pre);
            ss[now].clear();

            vint & vec = per[i];
            for(int j : vec) for(int v : ss[pre])
            {
                ss[now].insert(j + v);
            }

            set<int>::iterator it = ss[now].end();
            it--;
            while(ss[now].size() > 10)
            {
                ss[now].erase(it);
                it--;
            }
        }

        for(int v : ss[now])
            printf(" %d", v);

        puts("");
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值