codeforces 632e dp

题意是给你n种商品,每种商品数量无限,有各自的价格,现在需要买k个商品,设所得到的总花费为w,问你所有可能的w的值。

这题不会,一直在纠结“刚好k个”怎么处理,看了别人代码懂的。
关键点在于去掉“刚好”,于是把所有价格减去最小的价格,即变为相对价格。那么一定存在某样商品价格为0,那么我们可以任意地在某个总价的基础上增加价格为0的商品数量而对总价不产生影响。
设dp[i]表示组成总价为i时需要的最少的商品数量,现在如果dp[i]<=k则满足要求。然后求出来dp数组就可以了。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<vector>
#include<string>
#include<map>
#include<algorithm>
#define LL long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int N=1005;
const int inf=0x3f3f3f3f;
int a[N];
int dp[N*N];
int main()
{
    //freopen("a.txt","r",stdin);
    int n,k;
    while(~scanf("%d%d",&n,&k))
    {
        int MIN=1e9,MAX=-1;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),MIN=min(MIN,a[i]);
        for(int i=1;i<=n;i++)
        {
            a[i]=a[i]-MIN;
            MAX=max(MAX,a[i]);
        }
        sort(a+1,a+n+1);
        n=unique(a+1,a+n+1)-a-1;
        MAX*=k;
        memset(dp,inf,sizeof(dp));
        dp[0]=0;
        for(int i=1;i<=MAX;i++)
        {
            for(int j=1;j<=n&&a[j]<=i;j++)
            dp[i]=min(dp[i],dp[i-a[j]]+1);
        }
        int flag=0;
        for(int i=0;i<=MAX;i++)
        {
            if(dp[i]>k)continue;
            if(flag==0)flag=1;
            else printf(" ");
            printf("%d",i+MIN*k);
        }
        printf("\n");
    }
    return 0;
}

你可能感兴趣的:(dp,codeforces)