码迷,mamicode.com
首页 > 其他好文 > 详细

codevs 2451 互不侵犯(状丫dp)

时间:2016-08-15 22:26:51      阅读:107      评论:0      收藏:0      [点我收藏+]

标签:

/*
好神奇好神奇...表示自己要学的还很多
注意到n<=9 不是搜索就是状丫
搜索+剪枝 70分 枚举放或者不放
这里用状丫 f[i][j][k] 表示前i行 放了j个国王 i行的状态是k的方案数
转移的话 枚举下层的状态 算出这个状态中有几个国王 然后更新
复杂度 2^n*2^n*n*K*n 最后一个n是算国王数 这个可以预处理搞出来
还有一个问题就是 互相伤害的问题
首先在同一行里 相邻的不行 不同行的就左移右移一下就好了 顺带处理好两个状态能不能互相转移
最后Σf[n][K][i] 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 520
using namespace std;
int n,K,v1[maxn],v2[maxn][maxn],cnt[maxn];
long long ans,f[10][100][maxn];
void Get_v()
{
    for(int i=0;i<(1<<n);i++)
      if((i&(i>>1))==0)
        {
          v1[i]=1;int c=0;
          for(int j=i;j;j>>=1)c+=j&1;
            cnt[i]=c;
        }
    for(int i=0;i<(1<<n);i++)if(v1[i])
      for(int j=0;j<(1<<n);j++)if(v1[j])
        if((i&j)==0&&(i&(j>>1))==0&&(j&(i>>1))==0)
          v2[i][j]=1;
}
int main()
{
    cin>>n>>K;
    Get_v();
    for(int i=0;i<(1<<n);i++)
      f[1][cnt[i]][i]=1;
    for(int i=2;i<=n;i++)
      for(int j=0;j<(1<<n);j++)if(v1[j])
        for(int k=0;k<(1<<n);k++)if(v2[j][k])
          for(int r=cnt[j];r+cnt[k]<=K;r++)
            f[i][r+cnt[k]][k]+=f[i-1][r][j];
    for(int i=0;i<(1<<n);i++)
      ans+=f[n][K][i];
    cout<<ans<<endl;
    return 0;
}

 

codevs 2451 互不侵犯(状丫dp)

标签:

原文地址:http://www.cnblogs.com/yanlifneg/p/5774431.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!