POJ1010-STAMPS 搜索

这篇博客介绍了POJ1010-STAMPS问题,邮局根据特定规则销售邮票,包括邮票种类限制、面值总和要求等。博主分享了使用搜索策略解决该问题的思路,并强调了搜索过程中处理tie情况的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

STAMPS
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 19490 Accepted: 5712

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. 

链接

一、题意

        邮局想要向外出售邮票。给定邮票种类和每种邮票的面值,每种邮票假设有无限多张,不同种类可能有同样的面值。对于每一个顾客,当顾客需要总面值为k的邮票时,你需要按以下要求给他提供邮票:

                1.最多出售给一个顾客四张邮票

                2.邮票的面值总和为k

                3.若有多种组合,则优先输出邮票种类最多的组合

                4.若还有多种组合,则优先输出邮票总数最少的组合

                5.若还有多种组合,则优先输出最大面值较大的组合

                6.若还有多种组合,则输出tie

        具体输出要求见题目。

二、思路

        因为每个顾客最多只会得到四张邮票,所以采用搜索策略即可。对于没种可能的情况进行判断。注意搜索时可能先进入tie的情况,然后又找到更优解。所以在进入tie后还需要继续搜索。

三、代码

#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>
#include <numeric>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <utility>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>

using namespace std;
typedef long long ll;
const int MAXN = 100100;
const int MOD7 = 1000000007;
const int MOD9 = 1000000009;
const int INF = 2000000000;//0x7fffffff
const double EPS = 1e-9;
const double PI = 3.14159265358979;
const int dir_4r[] = { -1, 1, 0, 0 };
const int dir_4c[] = { 0, 0, -1, 1 };
const int dir_8r[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
const int dir_8c[] = { -1, 0, 1, -1, 1, -1, 0, 1 };

int stamps[MAXN], best[10], buf[10];
int bestn, bestc;//最优解时购买的邮票数和邮票种类
int flag;//0为无解,1为有解,2为多解
int total;//记录邮票总数

void check(int d, int cnt) {
	if (cnt < bestc)
		return;

	if (flag == 0) {
		flag = 1;
		bestn = d;
		bestc = cnt;
		for (int i = 0; i < bestn; ++i)
			best[i] = buf[i];
	}
	else if (flag == 1) {
		if (cnt == bestc && d == bestn && buf[d - 1] == best[bestn - 1]) {
			//出现多个最优解
			flag = 2;
		}
		else if (cnt > bestc || d < bestn || (d == bestn && buf[d - 1] > best[bestn - 1])) {
			//出现更优解
			bestn = d;
			bestc = cnt;
			for (int i = 0; i < bestn; ++i)
				best[i] = buf[i];
		}
	}
	else {
		if (cnt > bestc || d < bestn || (d == bestn && buf[d - 1] > best[bestn - 1])) {
			//出现更优解
			flag = 1;
			bestn = d;
			bestc = cnt;
			for (int i = 0; i < bestn; ++i)
				best[i] = buf[i];
		}
	}
}

//d表示搜索深度,cnt表示邮票种类
void dfs(int d, int index, int cnt, int sum, int val) {
	if (sum > val)
		return;
	if (sum == val) {
		check(d, cnt);
		return;
	}
	if (d == 4)
		return;

	for (int i = index; i < total; ++i) {
		buf[d] = stamps[i];
		int tmp = (d == 0 || i != index) ? 1 : 0;
		dfs(d + 1, i, cnt + tmp, sum + stamps[i], val);
	}
}

int main() {
	int val;

	while (scanf("%d", &val) != EOF) {
		total = 0;
		stamps[total++] = val;
		while (scanf("%d", &val) && val)
			stamps[total++] = val;
		sort(stamps, stamps + total);

		while (scanf("%d", &val) && val) {
			flag = 0;
			bestn = bestc = 0;
			dfs(0, 0, 0, 0, val);

			if (flag == 0)
				printf("%d ---- none\n", val);
			else if (flag == 1) {
				printf("%d (%d):", val, bestc);
				for (int i = 0; i < bestn; ++i)
					printf(" %d", best[i]);
				printf("\n");
			}
			else
				printf("%d (%d): tie\n", val, bestc);
		}
	}

	//system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值