北大oj1010——STAMPS

STAMPS

Time Limit: 1000MS Memory Limit: 10000K

Description

Have you done any Philately lately?
You have been hired by the Ruritanian Postal Service (RPS) to design their new postage software. The software allocates stamps to customers based on customer needs and the denominations that are currently in stock.
Ruritania is filled with people who correspond with stamp collectors. As a service to these people, the RPS asks that all stamp allocations have the maximum number of different types of stamps in it. In fact, the RPS has been known to issue several stamps of the same denomination in order to please customers (these count as different types, even though they are the same denomination). The maximum number of different types of stamps issued at any time is twenty-five.
To save money, the RPS would like to issue as few duplicate stamps as possible (given the constraint that they want to issue as many different types). Further, the RPS won't sell more than four stamps at a time.

Input

The input for your program will be pairs of positive integer sequences, consisting of two lines, alternating until end-of-file. The first sequence are the available values of stamps, while the second sequence is a series of customer requests. For example:
1 2 3 0 ; three different stamp types
7 4 0 ; two customers
1 1 0 ; a new set of stamps (two of the same type)
6 2 3 0 ; three customers
Note: the comments in this example are not part of the data file; data files contain only integers.

Output

For each customer, you should print the "best" combination that is exactly equal to the customer's needs, with a maximum of four stamps. If no such combination exists, print "none".
The "best" combination is defined as the maximum number of different stamp types. In case of a tie, the combination with the fewest total stamps is best. If still tied, the set with the highest single-value stamp is best. If there is still a tie, print "tie".
For the sample input file, the output should be:
7 (3): 1 1 2 3
4 (2): 1 3
6 ---- none
2 (2): 1 1
3 (2): tie
That is, you should print the customer request, the number of types sold and the actual stamps. In case of no legal allocation, the line should look like it does in the example, with four hyphens after a space. In the case of a tie, still print the number of types but do not print the allocation (again, as in the example).Don't print extra blank at the end of each line.

Sample Input

1 2 3 0 ; three different stamp types
7 4 0 ; two customers
1 1 0 ; a new set of stamps (two of the same type)
6 2 3 0 ; three customers

Sample Output

7 (3): 1 1 2 3
4 (2): 1 3
6 ---- none
2 (2): 1 1
3 (2): tie

这道题折磨了好久,刚开始还以为是背包问题,后来发现是遍历问题。遍历所有可能性,比较最优解。
有以下收获
1.因为问题只求一个最优解,所以在遍历的时候就可以寻求最优解了,而不是等到最后再计算。
2.做好剪枝。
3.有一个被忽视的剪枝:若数组里同样的数大于5个的时候,后面的事就可以不用加进数组里了。
4.以所有邮票for循环来进行递归比以从第一个物体开始计算可加4次来进行递归要快很多。

#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;

int stamps[120];
int tempstamps[120];
int maxIndex = 0;
vector<int> bestArray;
bool isTie = false;
int maxCnt = 0;

bool calcBestWay(int useTime, int lastValue, int curI, vector<int> array) {
    if (useTime >= 4) {
        return false;
    }
    if (lastValue <= 0) {
        return false;
    }
    int total = 0;
    for (int i = curI; i < maxIndex; i++) {
        if (lastValue < stamps[i]) {
            return false;
        }
        vector<int> outArray(array);
        outArray.push_back(i);
        if (lastValue == stamps[i]) {
            vector<int>::iterator it;
            int change = 0;
            int curNum = -1;
            for (it = outArray.begin(); it != outArray.end(); it++)
            {
                if (curNum != *it) {
                    change++;
                    curNum = *it;
                }
            }
            if (bestArray.empty()) {
                bestArray = outArray;
                sort(bestArray.begin(), bestArray.end());
                maxCnt = change;
            }
            else {
                sort(outArray.begin(), outArray.end());
                if (maxCnt < change) {
                    bestArray = outArray;
                    maxCnt = change;
                    isTie = false;
                }
                else if (maxCnt == change) {
                    if (bestArray.size() > outArray.size()){
                        bestArray = outArray;
                        isTie = false;
                    }
                    else if (bestArray.size() == outArray.size()) {
                        if (stamps[bestArray.back()] < stamps[outArray.back()]) {
                            bestArray = outArray;
                            isTie = false;
                        }
                        else if (stamps[bestArray.back()] == stamps[outArray.back()]) {
                            isTie = true;
                        }
                    }
                }
            }
            continue;
        }
        calcBestWay(useTime + 1, lastValue - stamps[i], i, outArray);
    }
    return false;
}

int main()
{
    int n;
    while (cin >> n) {
        int index = 0;
        while (n != 0) {
            tempstamps[index++] = n;
            cin >> n;
        }
        maxIndex = index;
        sort(tempstamps, tempstamps + index);
        int maxReply = 0;
        int curNum = 0;
        index = 0;
        for (int i = 0; i < maxIndex; i++) {
            if (curNum != tempstamps[i]) {
                curNum = tempstamps[i];
                maxReply = 1;
                stamps[index++] = tempstamps[i];
            }
            else {
                maxReply++;
                if (maxReply <= 5) {
                    stamps[index++] = tempstamps[i];
                }
            }
        }
        maxIndex = index;

        int n = -1;
        while (n != 0) {
            cin >> n;
            if (n == 0) {
                break;
            }
            vector<int> array;
            bestArray.clear();
            isTie = false;
            maxCnt = 0;
            calcBestWay(0, n, 0, array);

            if (bestArray.size() <= 0) {
                cout << n << " ---- none" << endl;
            }
            else if (isTie) {
                cout << n << " (" << maxCnt << "): tie" << endl;
            }
            else {
                cout << n << " (" << maxCnt << "):";
                vector<int>::iterator it = bestArray.begin();
                for (it; it != bestArray.end(); it++) {
                    cout << " " << stamps[*it];
                }
                cout << endl;
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

椰子糖莫莫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值