• P3092 [USACO13NOV]没有找零No Change


    ${color{Cyan}{>>Question}}$

    一道状压好题(少有的没看题解一遍$AC$的不是水题(自认为)的题(看来是我太菜了))

    首先看到$kleqslant 16$,$emm$,要么暴搜,要么状压

    再看$nleqslant 10^5$,$emm$,状压实锤了,但这$n$太大,显然其中状压$dp$的状态和转移中都不能有$n$(一有就炸了)

    看范围先想一维,令$f[i]$表示状态$i$下的什么

    P4329 [COCI2006-2007#1] Bond的经验,我们知道状态并不只表示了其中的选或不选,还可以表示选了多少个和选了哪些

    在这道题下,选了哪些就尤为重要了(因为就可以统计答案了),那差的就是能不能买到$n$个或者说能买多少个

    试着令$f[i]$表示状态$i$下最多能买多少个,枚举当前用哪个硬币(假设是第$j$号硬币)

    那之前的状态为$f[i-left { j ight }]$(也就是说$j$号硬币要从$f[i-left { j ight }]+1$号物品开始买),

    那现在的问题就只剩下$j$号硬币从某处开始最多能买多少个物品,这可以用前缀和$+$二分提前预处理出来

    令$cnt[i][j]$表示$i$号硬币从$j$处开始最多买多少个,$r$表示最远的那个编号

    显然有$$sum[r]-sum[j-1]leqslant val[i]$$

    即$$r=upperbound(val[i]+sum[j-1])-1$$

    如此,转移就出来了$$f[i] = maxleft { f[i-left { j ight }]+cnt[j][f[i-left { j ight }]+1] ight }$$

    上代码(写得好累啊$QwQ$)

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstdio>
     4 #include <cstring>
     5 #define ll long long
     6 using namespace std; 
     7 
     8 template <typename T> void in(T &x) {
     9     x = 0; T f = 1; char ch = getchar();
    10     while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
    11     while( isdigit(ch)) {x = 10 * x + ch - 48; ch = getchar();}
    12     x *= f;
    13 }
    14 
    15 template <typename T> void out(T x) {
    16     if(x < 0) x = -x , putchar('-');
    17     if(x > 9) out(x/10);
    18     putchar(x%10 + 48);
    19 }
    20 //-------------------------------------------------------
    21 
    22 const int N = 1e6+5,M = 17;
    23 
    24 int k,n;
    25 int val[M],cst[M],cnt[M][N];
    26 ll sum[N];
    27 int f[1<<M];
    28 ll ans = -1;
    29 
    30 int main() {
    31     int i,j;
    32     in(k); in(n);
    33     for(i = 1;i <= k; ++i) in(val[i]);
    34     for(i = 1;i <= n; ++i) in(cst[i]),sum[i] = sum[i-1]+cst[i];
    35     for(i = 1;i <= k; ++i) {
    36         for(j = 1;j <= n; ++j) {
    37             cnt[i][j] = upper_bound(sum+1,sum+n+1,val[i]+sum[j-1])-sum-1-j+1;//r-j+1//debug val -> cst
    38         }
    39     }//预处理出i硬币在位置j向后延伸的最长长度
    40     memset(f,~0x3f,sizeof(f));
    41     f[0] = 0;
    42     for(i = 1;i < (1<<k); ++i) {
    43         for(j = 1;j <= k; ++j) {
    44             if(i&(1<<(j-1))) f[i] = max(f[i],f[i^(1<<(j-1))]+cnt[j][f[i^(1<<(j-1))]+1]);
    45         }
    46         if(f[i] >= n) {
    47             ll res = 0;
    48             for(j = 1;j <= k; ++j) if(!(i&(1<<(j-1)))) res += val[j];
    49             ans = max(res,ans);
    50         }
    51     }
    52     out(ans);
    53     return 0;
    54 }
  • 相关阅读:
    基于OWin的Web服务器Katana发布版本3
    如何在.NET上处理二维码
    .NET开源OpenID和OAuth解决方案Thinktecture IdentityServer
    ASP.NET Identity V2
    Azure Redis Cache
    CentOS 7 安装RabbitMQ 3.3
    ASP.Net MVC 5 in Xamarin Studio 5.2
    Centos 7.0 安装Mono 3.4 和 Jexus 5.6
    CentOS下GPT分区(转)
    CentOS下使用LVM进行分区(转)
  • 原文地址:https://www.cnblogs.com/mzg1805/p/11360291.html
Copyright © 2020-2023  润新知