zoukankan      html  css  js  c++  java
  • codevs 2451 互不侵犯(状丫dp)

    /*
    好神奇好神奇...表示自己要学的还很多
    注意到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;
    }
  • 相关阅读:
    UIButton和UIImageView的区别
    大道至简第八章读后感
    简单登录界面
    大道至简第七章读后感
    计算成绩代码
    大道至简第六章读后感
    产生随机数代码
    大道至简第五章读后感
    计算成绩算法
    加密算法
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/5774431.html
Copyright © 2011-2022 走看看