Mega Man's Mission UVA11795(状态压缩dp)

来源:互联网 发布:cc免费顶级域名注册 编辑:程序博客网 时间:2024/05/01 00:42

大意:
主角自己有一些武器,然后每个机器人身上有一些武器,每个机器人需要用特定的武器才能消灭。
问,有多少种消灭机器人的顺序。

思路:
用 dp[S][i] 表示现在消灭的机器人集合为S(获得的武器也隐含在其中了,不用再开一维),而且是通过消灭第i号机器人到这个状态,这个状态下的顺序总数。

我的代码用了一个atk[S][j] 数组,表示在消灭了S这个集合机器人的情况下,能不能消灭第j个机器人,这样方便一些。

#include<iostream>#include<string.h>#include<string>#include<algorithm>#include<stdio.h>#include<vector>#define LL long long intusing namespace std;LL dp[1<<17][17];int atk[1<<17][17];//?????????????????????????i????char grid[17][17];int n;void process(){    memset(atk,0,sizeof(atk));    for(int i=0;i<n;i++)    {        atk[0][i]=grid[0][i]-'0';    }    for(int i=1;i<(1<<n);i++)    {        for(int j=0;j<n;j++)        {            if( ((i)&(1<<j))==0 ) continue;            int subset=i-(1<<j);            for(int k=0;k<n;k++)            {                atk[i][k]|=atk[subset][k];            }            for(int k=0;k<n;k++)            {                atk[i][k]|=grid[j+1][k]-'0';            }        }    }}void solve(){    //?????????    memset(dp,0,sizeof(dp));    for(int i=0;i<n;i++)    {        dp[1<<i][i]=grid[0][i]-'0';    }    for(int i=1;i<(1<<n);i++)    {        for(int j=0;j<n;j++)        {            if( ((i)&(1<<j))==0 ) continue;            int subset=i-(1<<j);            if(subset==0) continue;            if(atk[subset][j]==1)            {                for(int k=0;k<n;k++)                {                    dp[i][j]+=dp[subset][k];                }            }        }    }}int main(){    int t;    cin>>t;    for(int CS=1;CS<=t;CS++)    {        cin>>n;        for(int i=0;i<=n;i++)        {            scanf("%s",grid[i]);        }        process();        solve();        LL ans=0;        for(int i=0;i<n;i++) ans+=dp[(1<<n)-1][i];        printf("Case %d: %lld\n",CS,ans);//23423423423    }    return 0;}
0 0
原创粉丝点击