Engineer Assignment dp

来源:互联网 发布:营业收入印花税的算法 编辑:程序博客网 时间:2024/06/05 19:19


状压dp 。

学习的时候唯一的疑问就是不知道怎么转换状态 。还是因为对状态压缩不是多么懂

刷了这个题就好多了  。


把能完成 第i 个任务的状态进行记录 。

之后用这个状态进行dp

最好用的就是二进制 。

1代表选过  0代表没选过  。

在这个上面进行状态压缩 。

代码注释下看  


#include <bits/stdc++.h>using namespace std;#define mo 205#define pus push_backint a[mo][mo],b[mo][mo];int tag[mo];int dp[mo][3000];vector<int > d[mo];int main(){    int t;    cin>>t;    int l=1;    while(t--)    {        int n,m;        cin>>n>>m;        for(int i=1;i<=n;i++)        {            d[i].clear();            cin>>a[i][0];            for(int j=1;j<=a[i][0];j++)                cin>>a[i][j];        }        for(int i=0;i<m;i++)        {            cin>>b[i][0];            for(int j=1;j<=b[i][0];j++)                cin>>b[i][j];        }        for(int i=1;i<=n;i++)        {            for(int j=0;j<(1<<m);j++)            {                memset(tag,0,sizeof(tag));                for(int k=0;k<m;k++)                {                    if(j&(1<<k))  //此代表k是否属于状态j 。                    {                        for(int r=1;r<=b[k][0];r++)                        {                            tag[b[k][r]]=1;                        }                    }                }                int flag=1;                for(int j=1;j<=a[i][0];j++)//如果这个状态可以完成i任务的话                {                    if(tag[a[i][j]]==0)                    {                        flag=0;                        break;                    }                }               // if(flag)cout<<j<<endl;                if(flag) d[i].pus(j);//将这个状态保存            }        }        memset(dp,0,sizeof(dp));        for(int i=1;i<=n;i++)        {            for(int j=0;j<(1<<m);j++)            {                for(int k=0;k<d[i].size();k++)                {                    int x=d[i][k];                    if((x|j)==j)//如果x状态属于j 的话  则代表 j-x的状态可以进行dp。和背包一样                    {                        dp[i][j]=max(dp[i][j],dp[i-1][j-x]+1);                    }                    //cout<<dp[i][j]<<' ';                }               // cout<<endl;                dp[i][j]=max(dp[i][j],dp[i-1][j]);            }        }        cout<<"Case #"<<l++<<": "<<dp[n][(1<<m)-1]<<endl;    }}


原创粉丝点击