• 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;
    }
  • 相关阅读:
    感悟贴2016-05-13
    操作系统原理部分
    java-NIO
    centos7下环境配置
    mysql 链接驱动问题
    ComboPooledDataSource 连接池耗完
    mvn使用问题
    js button onclick动作赋值操作
    git操作之git clean删除一些没有git add的文件
    VMware虚拟机网络设置
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/5774431.html
Copyright © 2020-2023  润新知