【hihocoder】状态压缩dp

来源:互联网 发布:顶级域名列表 编辑:程序博客网 时间:2024/05/23 01:17

 这是一个二维dp,我把其中一维抽出来放在tui中,意思是从一个状态递推下一个状态。

tui()中递推过程类似于背包。

本题的二维dp不像常见的右下角递推的二维dp,本题的递推方向是从0xxxx向0xxx0或0xxx1。

#include <iostream>#include <string.h>using namespace std; // 0xxxxx->0xxxx0,0xxxx1void tui(int a[],int b[],bool valid[],int W,int M){    int s=1<<(M-1),t=1<<M;    memset(b,0,t*sizeof(int));    for(int i=0;i<t;i++){        if(valid[i]){            int j=i&(~s);//@error: reset s bit should be i&(~s) not i^s            j=j<<1;            b[j]=max(b[j],a[i]);            b[j+1]=max(b[j+1],a[i]+W);        }    }}// judge if state n is valid, which means if its 1 bit is no more than Qbool isValid(int n,int Q){   int cnt=0;   while(n>0){       cnt++;       if(cnt>Q) return false;       n=n&(n-1);   }   return true;}int dp(int w[],int cnt[][1024],bool valid[],int N,int M,int Q){    if(N==0||Q==0) return 0;    int t=1<<M;     for(int i=0;i<t;i++){        valid[i]=isValid(i,Q);        cnt[0][i]=cnt[1][i]=0;    }    // dp    cnt[0][1]=w[0]; //edge condition    for(int i=1;i<N;i++){        tui(cnt[(i+1)%2],cnt[i%2],valid,w[i],M);    }    int maxN=0;    for(int i=0;i<t;i++){        if(valid[i]){            maxN=max(maxN,cnt[(N-1)%2][i]);        }    }    return maxN;}int main(){    int N,M,Q;    cin>>N>>M>>Q;    int w[1024],cnt[2][1024];bool valid[1024];    for(int i=0;i<N;i++){        cin>>w[i];    }    cout<<dp(w,cnt,valid,N,M,Q)<<endl;    return 0;}


0 0