zoukankan      html  css  js  c++  java
  • CF632E Thief in a Shop

    题目链接:http://codeforces.com/contest/632/problem/E

    题目大意:

      从 (n) 个不同的数中取 (k) 个(可重复取)并加起来,问最多能得到多少种不同的和,从小到大输出所有的和。

      ((1 le n,k,a_i le 1000))

    知识点:  DP

    解题思路:

      首先明确一点:对于 (5s) 的时限,(O(1e9)) 的复杂度是可以过的,因此我们可以来考虑 (DP).

      具体的方法是:先把 (a[]) 数组从小到大排序,将 (a[0]) 视为 (0),即零点上移 (a[0]),则 (a[]) 数组中其他的数也要相应地减掉 (a[0])。对这个零点上移 的数组做 (dp),使得对每一个和所用的数的个数尽可能少,最后打印答案的时候再将零点复位,则对于需要数的个数小于等于 (k) 的和我们都是可以用 (a[]) 数组中的 (k) 个数取到的(此时 (0) 又变回了 (a[0]))。

    AC代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1004,inf=0x3f3f3f3f;
     4 
     5 int dp[maxn*maxn];
     6 int a[maxn],da[maxn];
     7 
     8 int main(){
     9     int n,k;
    10     scanf("%d%d",&n,&k);
    11     for(int i=0;i<=1000*k;i++)  dp[i]=inf;
    12     for(int i=0;i<n;i++)    scanf("%d",&a[i]);
    13     sort(a,a+n);
    14 
    15     for(int i=1;i<n;i++)
    16         da[i]=a[i]-a[0];
    17     dp[0]=0;
    18     for(int i=1;i<n;i++){
    19         for(int j=0;j<1000*k;j++){
    20             if(dp[j]<inf)
    21                 dp[j+da[i]]=min(dp[j+da[i]],dp[j]+1);
    22         }
    23     }
    24     
    25     for(int i=0;i<=1000*k;i++){
    26         if(dp[i]<=k)
    27             printf("%d ",i+k*a[0]);
    28     }printf("
    ");
    29     
    30     return 0;
    31 }
    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    ASP.NET上传文件的三种基本方法
    实例分析 equals 和 ==
    如何保证Web Service的安全
    Winform动态显示图片,数据流方式
    C# 文件保存到数据库中或者从数据库中读取文件
    简说Session
    NotifyIcon的简单使用
    c# Invoke和BeginInvoke 区别
    DataGridView 的 CurrentCellDirtyStateChanged事件用法
    十种发送邮件的方式
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/9071439.html
Copyright © 2011-2022 走看看