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;
}
时间: 2024-08-10 05:33:11

codevs 2451 互不侵犯(状丫dp)的相关文章

CODEVS 2451 互不侵犯

2451 互不侵犯 题目描述 Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 输入描述 Input Description 只有一行,包含两个数N,K ( 1 <=N <=9,  0 <= K <= N * N) 输出描述 Output Description 方案数. 样例输入 Sample Input 3 2 样例输出 Sample Output 16

1896 [SCOI2005]互不侵犯 状压dp

传送门 这是一道状压dp的经典例题 题目让输出所有可能的方案数 很显然 这是一道动态规划了 由于国王放置的位置有一定的限制 所以我们要在状态转移的过程中增加一维来存储状态 我们这一道题假设f[i][j][k] 意思是在前i行一共放置了j个国王 第i行国王放置的状态是k  存储的值是方案数 首先 我们可以先预处理出左右合法的每行的状态...(有点绕 就是说针对单独的一行 会有那些合法的状态 使得相邻的两个格子最多只能放置一个国王 没有相邻的国王 然后我们开始dp 我们分别枚举i k s i是当前枚

[SCOI2005]互不侵犯 (状压$dp$)

题目链接 Solution 状压 \(dp\) . \(f[i][j][k]\) 代表前 \(i\) 列中 , 已经安置 \(j\) 位国王,且最后一位状态为 \(k\) . 然后就可以很轻松的转移了... 记忆化搜索还是不够啊... 只能会正向 \(dp\) . Code #include<bits/stdc++.h> #define ll long long using namespace std; ll f[10][101][1100],n,K; ll js[1100],sum,ans;

_bzoj1087 [SCOI2005]互不侵犯King【dp】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1087 令f(i, j, k)表示前i列,二进制状态为j,已经用了k个国王的方案数,则 f(i, j, k) = sigma(i - 1, p, k - num[j]),其中可以从p状态转化到j状态,num[j]表示j状态下的国王数. 乍一看可能会超时,因为共有n * 2^n * n^2个状态,即状态数为O(n^3 * 2^n),转移的复杂度为O(2^n),因此总时间复杂度为O(n^3 *

C++之路进阶——状态压缩dp(互不侵犯)

2451 互不侵犯 2005年省队选拔赛四川 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 输入描述 Input Description 只有一行,包含两个数N,K ( 1 <=N <=9,  0 <= K <= N * N) 输出描述 Output Desc

BZOJ 1087: [SCOI2005]互不侵犯King( 状压dp )

简单的状压dp... dp( x , h , s ) 表示当前第 x 行 , 用了 h 个 king , 当前行的状态为 s . 考虑转移 : dp( x , h , s ) = ∑ dp( x - 1 , h - cnt_1( s ) , s' ) ( s and s' 两行不冲突 , cnt_1( s ) 表示 s 状态用了多少个 king ) 我有各种预处理所以 code 的方程和这有点不一样 ------------------------------------------------

BZOJ1087:[SCOI2005]互不侵犯King(状压DP)

[SCOI2005]互不侵犯King Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N) Output 方案数. Sample Input 3 2 Sample Output 16 分析: 经典的状压DP题目,可我竟然调了很长时间都没对,后来发现是DP枚举范围错

【状压dp】【bzoj 1087】【SCOI 2005】互不侵犯King

1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec Memory Limit: 162 MB Submit: 1991 Solved: 1185 Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N) Output 方案数. Sa

【状压dp】互不侵犯KING

互不侵犯KING Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3866  Solved: 2264[Submit][Status][Discuss] Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N) Outp