• hihocoder1044 状态压缩


    题目描述:

    编号为0~n-1的n个位置上分别有价值为w[0]~w[n-1]的n个物品,现在要选出一些物品,使得获得的价值最大,约束条件是:任意连续的m个物品中选取的物品数量不超过q。其中n<=1000, 2<=m<=10, 1<=q<=m, w[i]<=100.

    算法分析:

    状态定义:

    dp[i][s]表示:解决了物品0~i的选取问题,物品i-m+1, i-m+2, ..., i 的选取状态为s时,所获得的最大价值, 其中s的第0, 1, ..., m-1位分别指示物品i-m+1, i-m+2, ..., i的选取情况,对应位为1表示选取,为0表示不选取。

    状态转移:

    1.如果bitcnt(s)>q, 那么由s不可能转移出任何有效状态.

    2.如果bitcnt(s)<=q, 那么此时分为两种情况(设下一状态为ns):

      a.当不选取下一个物品时,ns=s>>1, 有转移方程:dp[i+1][ns] = max(dp[i+1][ns], dp[i][s]);

      b.当选取下一个物品时,ns=(s>>1)+(1<<(m-1)), 在bitcnt(ns)<=q的条件下,有转移方程:dp[i+1][ns] = max(dp[i+1][ns], dp[i][s]+w[i+1]).

    我的代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 #define MAXN 1100
     6 
     7 int w[MAXN], dp[MAXN][MAXN];
     8 
     9 int bitcnt(int x)
    10 {
    11     int cnt = 0;
    12     while(x)
    13     {
    14         if(x&1)    ++cnt;
    15         x = x>>1;
    16     }
    17     return cnt;
    18 }
    19 
    20 int main()
    21 {
    22     int n, m, q, ans;
    23     while(scanf("%d%d%d", &n, &m, &q)!=EOF)
    24     {
    25         for(int i=0; i<n; ++i)
    26             scanf("%d", &w[i]);
    27         ans = 0;
    28         if(n<m)
    29         {
    30             for(int s=0; s<(1<<n); ++s)
    31             {
    32                 if(bitcnt(s)<=q)
    33                 {
    34                     int sum=0;
    35                     for(int j=0; j<n; ++j) if((s>>j)&1) sum += w[j];
    36                     ans = max(ans, sum);
    37                 }
    38             }
    39             printf("%d
    ", ans);
    40             return 0;
    41         }
    42         
    43         memset(dp, 0, sizeof(dp));
    44         for(int s=0; s<(1<<m); ++s)
    45         {
    46             if(bitcnt(s)>q) continue;
    47             int sum = 0;
    48             for(int j=0; j<m; ++j) if((s>>j)&1) sum += w[j];
    49             dp[m-1][s] = sum;
    50         }
    51         for(int i=m-1; i<n-1; ++i)
    52         {
    53             for(int s=0; s<(1<<m); ++s)
    54             {
    55                 int bcnt = bitcnt(s);
    56                 int ns;
    57                 if(bcnt>q) continue;
    58                 ns = s>>1;
    59                 dp[i+1][ns] = max(dp[i+1][ns], dp[i][s]);
    60                 ns = (s>>1)+(1<<(m-1));
    61                 bcnt = bitcnt(ns);
    62                 if(bcnt>q) continue;
    63                 dp[i+1][ns] = max(dp[i+1][ns], dp[i][s]+w[i+1]);
    64             }
    65         }
    66         for(int s=0; s<(1<<m); ++s) ans = max(ans, dp[n-1][s]);
    67         printf("%d
    ", ans);
    68     }
    69     return 0;
    70 }

    题目来源:http://hihocoder.com/problemset/problem/1044

  • 相关阅读:
    正敲着代码,鼠标坏了!
    DB2 OLAP函数的使用(转)
    修剪矩形
    classpath和环境变量设置(转)
    MyEclipse断点调试JavaScript浅析(转)
    Onunload和onbeforeunload方法的异同
    db2中的coalesce函数(转)
    db2:根据TABLEID找table
    [转]DB2行列转换
    DB2删除数据时的小技巧
  • 原文地址:https://www.cnblogs.com/pczhou/p/4295514.html
Copyright © 2020-2023  润新知