USACO Stamps, DP

思路:

状态:设F[i]为组成面值为i所需要的最少的邮票数量
初始:F[0]=0
状态转移方程:
F[i]=min{F[ i-value[j] ] (j=1..n and i-value[j]>=0) }+1
最终答案:找到最小的F[i]>k,则答案为(i-1)

解析:F[i]具有最有子策略,即F[i]由F[0..i-1]中特定的最优解决定。枚举每种邮票j,F[ i-value[j] ]为若F[i]中有邮票j,它就是不贴邮票j时,组成面值为i-value[j]所需要的邮票数量的最小值。为使F[i]为最优解,应取F[ i-value[j] ]构成的集合中的元素的最小值,并加1,表示选取了j这张邮票。

时间复杂度(最坏情况):O(mnk) (m为每种邮票的面值最大值)


我的代码,注意这题的MAX要设定到2000000,因为这个出现了signal #11号错误好多次……
/* 
ID: wangxin12 
PROG: stamps
LANG: C++ 
*/ 
#include <iostream>
#include <vector>
#include <fstream>
#include <queue>
using namespace std;
#define MAX 2000000

int K, N; // K <= 200, N <= 50
vector<int> cents;
int dp[MAX + 1];

int main() {
	ifstream fin("stamps.in");
	ofstream fout("stamps.out");

	int i, j;
	fin>>K>>N;
	
	for(i = 1; i <= N; i++) {
		fin>>j;
		cents.push_back(j);
	}

	::QuickSort(cents, 0, cents.size() - 1);

	//init 初始状态
	for(i = 1; i <= MAX; i++)
		dp[i] = MAX;

	i = 1; 
	while( i ) {
		int minCost = MAX;
		for(j = 1; j <= N; j++) {
			if(i >= cents[j - 1]) {
				int temp = dp[ i - cents[j - 1] ] + 1;
				if(temp < minCost)
					minCost = temp;
			}
		}
		dp[i] = minCost;
		if(dp[i] > K) break;
		i++;
	}

	for(i = 1;  ; i++) {
		if(dp[i] == 0 || dp[i] > K)
			break;
	}

	fout<<i - 1<<endl;

	return 0;
}


--------------------------------------------------------------------------------------------------

Given a set of N stamp values (e.g., {1 cent, 3 cents}) and an upper limit K to the number of stamps that can fit on an envelope, calculate the largest unbroken list of postages from 1 cent to M cents that can be created.

For example, consider stamps whose values are limited to 1 cent and 3 cents; you can use at most 5 stamps. It's easy to see how to assemble postage of 1 through 5 cents (just use that many 1 cent stamps), and successive values aren't much harder:

  • 6 = 3 + 3
  • 7 = 3 + 3 + 1
  • 8 = 3 + 3 + 1 + 1
  • 9 = 3 + 3 + 3
  • 10 = 3 + 3 + 3 + 1
  • 11 = 3 + 3 + 3 + 1 + 1
  • 12 = 3 + 3 + 3 + 3
  • 13 = 3 + 3 + 3 + 3 + 1.

However, there is no way to make 14 cents of postage with 5 or fewer stamps of value 1 and 3 cents. Thus, for this set of two stamp values and a limit of K=5, the answer is M=13.

The most difficult test case for this problem has a time limit of 3 seconds.

PROGRAM NAME: stamps

INPUT FORMAT

Line 1:Two integers K and N. K (1 <= K <= 200) is the total number of stamps that can be used. N (1 <= N <= 50) is the number of stamp values.
Lines 2..end:N integers, 15 per line, listing all of the N stamp values, each of which will be at most 10000.

SAMPLE INPUT (file stamps.in)

5 2
1 3

OUTPUT FORMAT

Line 1:One integer, the number of contiguous postage values starting at 1 cent that can be formed using no more than K stamps from the set.

SAMPLE OUTPUT (file stamps.out)

13
 
 

描述

已知一个 N 枚邮票的面值集合(如,{1 分,3 分})和一个上限 K —— 表示信封上能够贴 K 张邮票。计算从 1 到 M 的最大连续可贴出的邮资。

例如,假设有 1 分和 3 分的邮票;你最多可以贴 5 张邮票。很容易贴出 1 到 5 分的邮资(用 1 分邮票贴就行了),接下来的邮资也不难:

6 = 3 + 3 
7 = 3 + 3 + 1 
8 = 3 + 3 + 1 + 1 
9 = 3 + 3 + 3 
10 = 3 + 3 + 3 + 1 
11 = 3 + 3 + 3 + 1 + 1 
12 = 3 + 3 + 3 + 3 
13 = 3 + 3 + 3 + 3 + 1

然而,使用 5 枚 1 分或者 3 分的邮票根本不可能贴出 14 分的邮资。因此,对于这两种邮票的集合和上限 K=5,答案是 M=13。

[规模最大的一个点的时限是3s]


小提示:因为14贴不出来,所以最高上限是13而不是15


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值