1. 程式人生 > >FZUOJ Problem 2200 cleaning DP

FZUOJ Problem 2200 cleaning DP

nbsp n) logs ret inpu uoj ++ link print

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; }

FZUOJ Problem 2200 cleaning DP