您的位置:首页 > 其它

FZUOJ Problem 2200 cleaning DP

2017-07-30 14:09 363 查看
[b]Problem 2200 cleaning[/b]



Problem Description

N个人围成一圈在讨论大扫除的事情,需要选出K个人。但是每个人与他距离为2的人存在矛盾,所以这K个人中任意两个人的距离不能为2,他们想知道共有多少种方法。



Input

第一行包含一个数T(T<=100),表示测试数据的个数。

接下来每行有两个数N,K,N表示人数,K表示需要的人数(1<=N<=1000,1<=K<=N)。



Output

输出满足题意的方案数,方案数很大,所以请输出方案数mod 1,000,000,007 后的结果。



Sample Input

2
4 2
8 3



Sample Output

4
16



Source

FOJ有奖月赛-2015年10月

[b]题解:[/b]
  设定 f[k][h] [i][j] 表示在不考虑环的清形下第一,二位置上的选择状态为k,h下,前i个选了j个人的方案数
    dp[k][h][i][j], 表示在考虑环的清形下第一,二位置上的选择状态为k,h下,前i个选了j个人的方案数
  那么对于f数组的递推,当前第i位置选与不选,i-1位置选与不选有
        f[k][h] = f[k][h][ii-1][j] +f[k][h][i-3][j-1] + f[k][h][i-4][j-2];
  对于dp数组转移同理就是拿f数组来更新
  具体看代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
typedef unsigned long long ULL;
const long long INF = 1e18+1LL;
const double pi = acos(-1.0);
const int N = 1e3+20, M = 1e6+10, mod = 1e9+7,inf = 2e9;

void update(int x,int& y) {
y += x;
if(y > mod) y -= mod;
}
int T,dp[2][2]

,f[2][2]

;//前i个人选j人,前两人状态
void init() {
dp[0][0][0][0] = 1;
dp[0][0][1][0] = 1;
dp[1][0][1][1] = 1;
dp[0][0][2][0] = 1;
dp[1][0][2][1] = 1;
dp[0][1][2][1] = 1;
dp[1][1][2][2] = 1;

dp[0][0][3][0] = 1;

dp[0][0][3][1] = 1;
dp[0][1][3][1] = 1;
dp[1][0][3][1] = 1;

dp[1][1][3][2] = 1;
dp[1][0][3][2] = 1;
dp[0][1][3][2] = 1;

dp[1][1][3][3] = 1;

for(int i = 0; i < 2; ++i) {
for(int j = 0; j < 2; ++j) {
for(int k = 0; k <= 3; ++k) {
for(int h = 0; h <= k; ++h)
f[i][j][k][h] = dp[i][j][k][h];
}
}
}
f[1][1][3][3] = 0;
f[1][0][3][2] = 0;
for(int k = 0; k < 2; ++k) {
for(int h = 0; h < 2; ++h) {
for(int i = 4; i <= 1000; ++i) {
for(int j = 0; j <= i; ++j) {
//不选, i-1选
if(i >= 5) {
if(!k && j >= 1) update(f[k][h][i-4][j-1],dp[k][h][i][j]);
if(!k && j >= 2)
if(i >= 5)update(f[k][h][i-5][j-2],dp[k][h][i][j]);
}
else {
if(!k && j >= 1) update(f[k][h][i-2][j-1],dp[k][h][i][j]);
}

//i不选,i-1不选
update(f[k][h][i-2][j],dp[k][h][i][j]);
//i位置选,i-1不选
if(!h&&j>=1)update(f[k][h][i-3][j-1],dp[k][h][i][j]);

//i位置选,i-1选
if(!k&&!h&&j>=2)
update(f[k][h][i-4][j-2],dp[k][h][i][j]);

update(f[k][h][i-1][j],f[k][h][i][j]);
if(i>=3&&j>=1)update(f[k][h][i-3][j-1],f[k][h][i][j]);
if(i>=4&&j>=2)update(f[k][h][i-4][j-2],f[k][h][i][j]);
}
}
}
}
}
int main() {
init();
scanf("%d",&T);
while(T--) {
int k,n;
scanf("%d%d",&n,&k);
int ans = 0;
for(int i = 0; i < 2; ++i) {
for(int j = 0; j < 2; ++j) {
update(dp[i][j]
[k],ans);
}
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: