思路:
状态:设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