题意:
按照一定的顺序消灭n个机器人,每消灭一个机器人就可得到它的武器,每个机器人只有用特定的武器才能消灭,现在给定一个初始的武器,它能消灭一些机器人,每个机器人的武器能消灭那些机器人也给你了,现在要你求消灭n个机器人的顺序总数;
思路:
dp[i][k]表示在第i次操作时的用k表示已经挂掉的机器人的操作顺序数;
枚举第i次要攻击的机器人j;dp[i][x]+=dp[i-1][k];x是挂到j后k与j表示的状态;
AC代码:
/************************************************
┆ ┏┓ ┏┓ ┆
┆┏┛┻━━━┛┻┓ ┆
┆┃ ┃ ┆
┆┃ ━ ┃ ┆
┆┃ ┳┛ ┗┳ ┃ ┆
┆┃ ┃ ┆
┆┃ ┻ ┃ ┆
┆┗━┓ ┏━┛ ┆
┆ ┃ ┃ ┆
┆ ┃ ┗━━━┓ ┆
┆ ┃ AC代马 ┣┓┆
┆ ┃ ┏┛┆
┆ ┗┓┓┏━┳┓┏┛ ┆
┆ ┃┫┫ ┃┫┫ ┆
┆ ┗┻┛ ┗┻┛ ┆
************************************************ */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <bits/stdc++.h>
#include <stack>
using namespace std;
#define For(i,j,n) for(int i=j;i<=n;i++)
#define mst(ss,b) memset(ss,b,sizeof(ss));
typedef long long LL;
template<class T> void read(T&num) {
char CH; bool F=false;
for(CH=getchar();CH<‘0‘||CH>‘9‘;F= CH==‘-‘,CH=getchar());
for(num=0;CH>=‘0‘&&CH<=‘9‘;num=num*10+CH-‘0‘,CH=getchar());
F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p) {
if(!p) { puts("0"); return; }
while(p) stk[++ tp] = p%10, p/=10;
while(tp) putchar(stk[tp--] + ‘0‘);
putchar(‘\n‘);
}
const LL mod=1e9+7;
const double PI=acos(-1.0);
const int inf=1e9;
const int N=(1<<18);
const int maxn=(1<<8);
const double eps=1e-8;
char s[20][20];
int num[20],sword[N],n;
LL dp[18][N];
inline int getnum(int x)
{
// int len=strlen(s[x]);
int ans=0;
For(i,0,n-1)
{
if(s[x][i]==‘1‘)ans+=(1<<i);
}
return ans;
}
int main()
{
int t,Case=0;
read(t);
while(t--)
{
read(n);
scanf("%s",s[0]);
sword[0]=getnum(0);
mst(dp,0);
For(i,1,n)
{
scanf("%s",s[i]);
num[i]=getnum(i);
}
For(i,1,(1<<n)-1)//预处理出每个状态下得到的武器情况
{
sword[i]=sword[0];
for(int j=0;j<n;j++)
{
if(i&(1<<j))sword[i]=(sword[i]|num[j+1]);
}
}
dp[0][0]=1;
For(i,1,n)
{
For(j,1,n)
{
for(int k=0;k<(1<<n);k++)
{
if(k&(1<<(j-1)))continue;//如果第j个机器人已经挂掉就略过;
if(sword[k]&(1<<(j-1)))dp[i][k|(1<<(j-1))]+=dp[i-1][k];//如果有干掉第j个机器人的武器
}
}
}
LL ans=dp[n][(1<<n)-1];
printf("Case %d: %lld\n",++Case,ans);
}
return 0;
}
原文:http://www.cnblogs.com/zhangchengc919/p/5719705.html