FZUOJ Problem 2200 cleaning DP

Problem 2200 cleaning

 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月

题解:

  设定 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][N][N],f[2][2][N][N];//前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][n][k],ans);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-10-17 20:22:58

FZUOJ Problem 2200 cleaning DP的相关文章

FZU Problem 2200 cleaning dp

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 后的结果. Sam

BZOJ 2298 problem a(DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2298 题意:一次考试共有n个人参加,第i个人说:“有ai个人分数比我高,bi个人分数比我低.”问最少有几个人没有说真话(可能有相同的分数) 思路:对于第i个人来说,区间[ai+1,n-bi]的人的分数相同.那么我们用sum[L][R]表示区间[L,R]中总人数.用f[i]表示前i个人中说真话的最大人数,那么f[j]=max(f[i-1]+sum[i][j]). map<pair<in

fzuoj Problem 2236 第十四个目标(树状数组+dp)

Problem 2236 第十四个目标  Problem Description 目暮警官.妃英里.阿笠博士等人接连遭到不明身份之人的暗算,柯南追踪伤害阿笠博士的凶手,根据几起案件现场留下的线索发现凶手按照扑克牌的顺序行凶.在经过一系列的推理后,柯南发现受害者的名字均包含扑克牌的数值,且扑克牌的大小是严格递增的,此外遇害者与毛利小五郎有关. 为了避免下一个遇害者的出现,柯南将可能遭到暗算的人中的数字按关联程度排列了出来,即顺序不可改变.柯南需要知道共有多少种可能结果,满足受害人名字出现的数字严格

fzuoj Problem 2179 chriswho

http://acm.fzu.edu.cn/problem.php?pid=2179 Problem 2179 chriswho Accept: 57    Submit: 136 Time Limit: 10000 mSec    Memory Limit : 327680 KB  Problem Description Chriswho很喜欢数字,特别喜欢一种数字,它能整除它的每一位数字(如果该位是0当做能整除),比如说126这个数字他就很喜欢,因为126%1=126%2=126%6=0.为

fzuoj Problem 2177 ytaaa

http://acm.fzu.edu.cn/problem.php?pid=2177 Problem 2177 ytaaa Accept: 113    Submit: 265Time Limit: 2000 mSec    Memory Limit : 32768 KB  Problem Description Ytaaa作为一名特工执行了无数困难的任务,这一次ytaaa收到命令,需要炸毁敌人的一个工厂,为此ytaaa需要制造一批炸弹以供使用. Ytaaa使用的这种新型炸弹由若干个炸药组成,每

fzuoj Problem 2129 子序列个数

http://acm.fzu.edu.cn/problem.php?pid=2129 Problem 2129 子序列个数 Accept: 162    Submit: 491Time Limit: 2000 mSec    Memory Limit : 32768 KB  Problem Description 子序列的定义:对于一个序列a=a[1],a[2],......a[n].则非空序列a'=a[p1],a[p2]......a[pm]为a的一个子序列,其中1<=p1<p2<..

HDU 5293 TREE CHAIN PROBLEM LCT+树形DP

题解链接 代码链接 链接 Tree chain problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 35    Accepted Submission(s): 8 Problem Description Coco has a tree, whose vertices are conveniently labeled by 1

bzoj 1700: [Usaco2007 Jan]Problem Solving 解题 ——dp

Description 过去的日子里,农夫John的牛没有任何题目. 可是现在他们有题目,有很多的题目. 精确地说,他们有P (1 <= P <= 300) 道题目要做. 他们还离开了农场并且象普通人一样找到了工作. 他们的月薪是M (1 <= M <= 1000) 元. 他们的题目是一流的难题,所以他们得找帮手.帮手们不是免费的,但是他们能保证在一个月内作出任何题目.每做一道题需要两比付款, 第一笔A_i(1 <= A_i <= M) 元在做题的那一个月初支付, 第二

FZUOJ Problem 2178 礼物分配

Problem 2178 礼物分配 题目链接: Click Here~ Problem Description 在双胞胎兄弟Eric与R.W的生日会上,他们共收到了N个礼物,生日过后他们决定分配这N个礼物(numv+numw=N).对于每个礼物他们俩有着各自心中的价值vi和wi,他们要求各自分到的礼物数目|numv-numw|<=1,并且各自所衡量的礼物价值的差值|sumv-sumw|尽可能小,现在他们想知道最小的差值是多少.  Input 第一行为一个整数表示数据组数T. 接下来T组数组,每组