hihocoder #1044 : 状态压缩·一 状压DP

http://hihocoder.com/problemset/problem/1044

可以看出来每一位的选取只与前m位有关,我们把每个位置起始的前m位选取状态看出01序列,就可以作为一个数字来存储,那么将其作为状态,dp[i][j]就是第i个座位前m个座位选取情况为j的最大垃圾处理量。然后取这个序列的后m-1位,和当前位取0/1的情况分别做合法性判断,然后做状态转移即可。

#include <iostream>
using namespace std;
const int N=1005;
const int inf=99999999;
int dp[N][2000];
int n,m,q;
int w[N];
int cntb(int num)
{
    int c=0;
    while(num)
        c+=num%2,num>>=1;
    return c;
}
int main()
{
    cin.sync_with_stdio(false);
    while(cin>>n>>m>>q)
    {
        for(int i=1; i<=n; i++)
            cin>>w[i];
        for(int i=0; i<(1<<m); i++)
            dp[0][i]=-inf;
        dp[0][0]=0;
        int d=1<<(m-1);
        for(int i=1; i<=n; i++)
        {
            for(int j=0;j<(1<<m);j++)
                dp[i][j]=-inf;
            for(int j=0;j<(1<<m);j++)
            {
                int qc=cntb(j>>1);
                if(qc>q)continue;
                if(qc==q)dp[i][j>>1]=max(dp[i][j>>1],dp[i-1][j]);
                else
                {
                    dp[i][d+(j>>1)]=max(dp[i][d+(j>>1)],dp[i-1][j]+w[i]);
                    dp[i][j>>1]=max(dp[i][j>>1],dp[i-1][j]);
                }
            }
        }
        int ans=-inf;
        for(int i=0;i<(1<<m);i++)
          ans=max(dp[n][i],ans);
        cout<<ans<<endl;
    }
    return 0;
}

 

posted @ 2018-01-25 15:11  Luke_Ye  阅读(158)  评论(0编辑  收藏  举报