zoukankan      html  css  js  c++  java
  • [USACO13NOV]No Change

    题目大意:
      你有k(k<=16)个硬币,每个硬币都有自己的面值。
      现在你要给n件商品付钱,每件商品也有自己的价格。
      然而老板是个奸商,他绝对不会给你找钱。
      你每次付钱只能用一个硬币,但是你可以一次性买很多商品。
      问你最后最多还能留下多少钱。

    思路:
      状压DP。
      f[i]表示状态为i时能买的商品数,i表示你用了哪些硬币。
      从小到大枚举每个状态i,然后枚举状态i中的硬币j,是这次付款用的硬币。
      二分找一下这些硬币最多能买前面连续的多少个商品。
      如果j不在i中,就算作最后剩下的硬币。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<algorithm>
     4 inline int getint() {
     5     register char ch;
     6     while(!isdigit(ch=getchar()));
     7     register int x=ch^'0';
     8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     9     return x;
    10 }
    11 const int K=16,N=100001;
    12 int v[K],sum[N],f[1<<K];
    13 int main() {
    14     const int k=getint(),n=getint();
    15     for(register int i=0;i<k;i++) {
    16         v[i]=getint();
    17     }
    18     for(register int i=1;i<=n;i++) {
    19         sum[i]=sum[i-1]+getint();
    20     }
    21     int ans=-1;
    22     for(register int i=0;i<(1<<k);i++) {
    23         int rem=0;
    24         for(register int j=0;j<k;j++) {
    25             if(i&(1<<j)) {
    26                 f[i]=std::max(f[i],int(std::upper_bound(&sum[0],&sum[n+1],sum[f[i^(1<<j)]]+v[j])-sum-1));
    27             } else {
    28                 rem+=v[j];
    29             }
    30         }
    31         if(f[i]==n) {
    32             ans=std::max(ans,rem);
    33         }
    34     }
    35     printf("%d
    ",ans);
    36     return 0;
    37 }
  • 相关阅读:
    51nod_1445 变色DNA 最短路模板 奇妙思维
    51nod_1459 最短路 dijkstra 特调参数
    UVA_10653 公主与王子 #刘汝佳DP题刷完计划
    HOJ 13819 Height map
    51nod_1255字典序最小的子序列
    电梯设计需求调研报告
    梦断代码读后感
    求一循环数组的最大子数组的和
    求二维数组中最大子数组的和
    四则运算
  • 原文地址:https://www.cnblogs.com/skylee03/p/7743480.html
Copyright © 2011-2022 走看看