USACO / Stamps(DP)

描述

已知一个 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]

格式

PROGRAM NAME: stamps

INPUT FORMAT:

(file stamps.in)

第 1 行: 两个整数,K 和 N。K(1 <= K <= 200)是可用的邮票总数。N(1 <= N <= 50)是邮票面值的数量。

第 2 行 .. 文件末: N 个整数,每行 15 个,列出所有的 N 个邮票的面值,每张邮票的面值不超过 10000。

OUTPUT FORMAT:

(file stamps.out)

第 1 行:一个整数,从 1 分开始连续的可用集合中不多于 K 张邮票贴出的邮资数。

SAMPLE INPUT

5 2
1 3

SAMPLE OUTPUT 

13
分析:
简单DP题。水题浪费时间还是太多。。。
先说下思路:首先想到设b[i]表示i可不可以被表示,然后b[i]=b[i-a[0]] || b[i-a[1]] || ......b[i-a[j]]算出每个i,然后看最大连续的数到哪里。
后来发现这道题有个限制就是邮票最多只能用K张。所以简单换了下方程:设f[i]表示能贴出i需要的最少邮票数。b[i]的计算公式还是一样的,只不过要加上一个限制条件,f[i-a[j]]<K. ( j=0..N ) 但是这个方法有个缺陷,不知道把i算到哪里合适。当然这道题的最大可能是200*10000。
但马上就又可以想到一个更直接且更省空间的方法:1.根本不需要把b[i]记录下来。因为是求从1开始连续的,所以到我们算到的这个i为止,前面的数都是ok的。(即b[i]=1),所以算当前b[i]就可以利用前面的任何数。2.跳出条件,不需要非算到200*10000,一旦算的i不能贴出,则可以立刻跳出。并输出i-1。理由同上,因为题目是让求从1开始可以连续到最大的数。
代码:
/*
ID:138_3531
LANG:C++
TASK:stamps
*/


#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <climits>

using namespace std;

int f[2001000];//能贴出i需要的最少邮票数
int main()
{
    ifstream fin("stamps.in");
    ofstream fout("stamps.out");


    int i;
    int K,N;


    int ok;
    int min;
    int a[50];
    memset(f,0,sizeof(f));
    f[0]=1;
    fin>>K>>N;


    for (i=0;i<N;i++)
        fin>>a[i];


    for (i=1;;i++)
    {
        ok=0;
        min=INT_MAX;


        for (int j=0;j<N;j++)
        {
            if (i-a[j]>=0)
                if ((f[i-a[j]]<K+1)&&(f[i-a[j]]>0))
                {
                    ok=1;
                    if (f[i-a[j]]+1<min)
                        min=f[i-a[j]]+1;
                }
        }


        if (!ok)
            break;
        f[i]=min;
    }


    fout<<i-1<<endl;


    return 0;
}
原文地址:https://www.cnblogs.com/AbandonZHANG/p/2598262.html