UVA 11795 Mega Man's Mission

题意:最开始有一些武器,要消灭掉n个机器人,干掉一个机器人以后可以获得它的武器,每一个武器能消灭的机器人也不同,问有多少方案干掉所有的机器人。

思路:很明显的状压dp……用一个二进制数表示已经干掉的机器人,equip[state]代表在该状态下获取的武器能干掉的机器人。那么状态如何转移呢?对于一个状态state来说,假如这个状态干掉了k个机器人,那么它就可以从干掉k-1个机器人的状态转移过来(注意这里被干掉的k-1个机器人要包含在state被干掉的机器人中),并且这个状态获得的武器要能干掉与这个状态缺少的那一个机器人。

 

代码:

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=1<<17;
ll dp[maxn];
int equip[maxn];
int weapon[17],p[17];
int n;
vector<int>s[17];
void Init()
{
    memset(dp,0,sizeof(dp));
    memset(equip,0,sizeof(equip));
    for(int i=0;i<=n;++i) p[i]=1<<i;
    for(int i=0;i<=n;++i)
      s[i].clear();
}
void getState()
{
    int N=p[n];
    equip[0]=weapon[0];
    int cnt=0,state,j;
    for(int i=1;i<N;++i)
    {
        state=i;cnt=0;
        equip[i]|=weapon[0];
        for(j=n-1;j>=0;--j)
        {
            if(state&p[j])
            {
                cnt++;
                equip[i]|=weapon[n-j];
            }
        }
        s[cnt].push_back(state);
    }
}
void solve()
{
    dp[0]=1;
    int state,i,j,k,pre;
    for(i=1;i<=n;++i)
        for(j=0;j<s[i].size();++j)
        {
            state=s[i][j];
            for(k=n-1;k>=0;--k)
            {
                if(state&p[k])
                {
                    pre=state^p[k];
                    if(equip[pre]&p[k])
                      dp[state]+=dp[pre];
                }
            }
        }
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int t,tcase=0;
    char str[20];
    scanf("%d",&t);
    while(t--)
    {
        tcase++;
        scanf("%d",&n);
        Init();
        int j;
        for(int i=0;i<=n;++i)
        {
            scanf("%s",str);
            j=0;
            for(int k=0;k<n;++k)
                if(str[k]=='1') j|=p[n-k-1];
            weapon[i]=j;
        }
        getState();
        solve();
        printf("Case %d: %lld\n",tcase,dp[p[n]-1]);
    }
    return 0;
}


 

你可能感兴趣的:(dp)