FZU 2200 cleaning dp+预处理

Problem 2200 cleaning

Accept: 10    Submit: 11
Time Limit: 1000 mSec    Memory Limit : 65536 KB

 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

24 28 3

 Sample Output

416



链接:http://acm.fzu.edu.cn/problem.php?pid=2200


做法:
dp 一维,第几个人,第二维是已经选了几个人,第三维是当前的状态,0 表示当前这位没选,前一位也没选,1表示当前这位没选,前一位选了,2,3类似。

枚举开头两个人的状态,然后预处理dp ,当处理到 i+2 的时候,如果状态和开始枚举的一样,就把值加进real[i]中。预处理出来的real就是最后的答案


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <malloc.h>
#include <ctype.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <stack>
#include <queue>
#include <vector>
#include <deque>
#include <set>
#include <map>
#define ll long long//试试

ll dp[1010][1010][4];//人数
ll real[1010][1010]; 
ll mod = 1000000007;
void init()
{
	memset(real,0,sizeof real);
	for(int i=0;i<2;i++)//1
	{
		for(int j=0;j<2;j++)//2
		{
			memset(dp,0,sizeof dp);
			dp[2][0][i+j*2]=1;

			for(int ii=3;ii<=1002;ii++)//位置
			{
				for(int jj=0;jj<=ii+2;jj++)//人数
				{
					for(int a=0;a<4;a++)//前一个
					{
						if((a&2)==0)
							dp[ii][jj][0]=(dp[ii][jj][0]+dp[ii-1][jj][a])%mod; 

						if((a&2))
							dp[ii][jj][1]=(dp[ii][jj][1]+dp[ii-1][jj][a])%mod;

						if((a&1)==0&&(a&2)==0&&jj)
							dp[ii][jj][2]=(dp[ii][jj][2]+dp[ii-1][jj-1][a])%mod;

						if((a&1)==0&&(a&2)&&jj)
							dp[ii][jj][3]=(dp[ii][jj][3]+dp[ii-1][jj-1][a])%mod;
					}

					for(int a=0;a<4;a++)
					{
						if((a^(i+j*2))==0)//和初始状态没区别
						{
							real[ii-2][jj]=(real[ii-2][jj]+dp[ii][jj][a])%mod;
							//if(dp[ii][jj][a])
						//		int kkk=0;
						}
					}

					//if(i==0&&j==0)
				//	printf("ii %d   jj %d   dp %d \n",ii,jj,real[ii][jj]);
				}
			}
		}
	}

}

int main()
{
	init();
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n,kk;
		scanf("%d%d",&n,&kk);//

		int ans=0;
		printf("%I64d\n",real[n][kk]%mod);
		 


	}
	return 0;
}



你可能感兴趣的:(dp)