您的位置:首页 > 大数据 > 人工智能

MZ Training 2014 #5 E题

2014-10-09 16:49 197 查看
位运算及其坑爹。。。。



状态压缩dp题一道。

其实我是用记忆化搜索来规矩这道题的:先把未杀死任何机器人的情况入队,然后枚举:从1(0000000000000001)到2^17—1(1111111111111111)这些状态,1表示此机器人已被击杀,然后用s[i]保存i状态的方案数,fig[i]表示i状态可杀死的机器人(可能包含已死亡的机器人),这样就可以转移状态了。

这里我要提一句,姜大神就是吊,scanf("%1d",&x)这种输入很少有c++ers使用吧!在这道题上好多人用上了字符串,其实就可以用这个。

比如输入数据为6574895,那么你scanf("%1d",&x)之后呢,x就等于6了。再scanf("%1d%1d",&x,&y)呢,就是x=5,y=7了。是不是很吊!这可是姜大神想出来的哦。

<span style="font-size:18px;color:#6600cc;background-color: rgb(255, 153, 102);">#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
int t,n;
long long dp[270010];//处于i状态的情况总数为dp[i]
int fig[270010];
int can[50];
int sum;
void xishouliangmixiadanlinjia()
{
int q=0;
while(q<sum)
{
fig[q]=can[0];
for(int i=1;i<=n;i++)
{
if((q&(1<<(i-1)))!=0)
fig[q]|=can[i];
}
q++;
}
dp[0]=1;
q=0;
while(q<sum)
{
for(int j=0;j<n;j++)
{
if((q&(1<<j))==0 && (fig[q]&(1<<j))!= 0)
dp[q|(1<<j)] += dp[q];
}
q++;
}
printf("%lld\n", dp[sum-1]);
}

int main()
{
int tt;
scanf("%d",&t);
tt=t;
while(t--)
{
printf("Case %d: ",tt-t);
scanf("%d",&n);
sum=(1<<n);
memset(dp,0,sizeof(dp));
memset(can,0,sizeof(can));
memset(fig,0,sizeof(fig));
int x;//姜大神就是吊这种奇葩的输入方式都想得出来
for(int i=0;i<=n;i++)
{
for(int j=0;j<n;j++)
{
scanf("%1d",&x);
if(x==1) can[i]|=(1<<j);
}
}
xishouliangmixiadanlinjia();
}
return 0;
}</span>呵呵~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: