比赛 20120707 评测结果 AAAWWWWWWW
题目名称 奇怪的棋盘 最终得分 30
用户昵称 ZhouHang 运行时间 0.121 s
代码语言 C++ 内存使用 45.55 MiB
提交时间 2012-07-07 10:46:07
显示代码纯文本
/**
*Prob	: boarda
*Data	: 2012-7-7
*Sol	: 骗分
*/

#include <cstdio>
#include <cstring>
#include <algorithm>

#define MaxS 32768
#define MaxN 19
#define MaxK 19
#define oo 1000000007

using namespace std;

int n,K,maxh,ans;
int s[MaxN],h[MaxN],num[MaxS+10];
int f[MaxN][MaxK][MaxS+10];

void Search_1()
{
	for (int i=0; i<=MaxS; i++) {
		int tmp = i;
		num[i] = 0;
		while (tmp) {
			num[i]++;
			tmp&=(tmp-1);
		}
	}
}
//第i行放在j,前i-1行为k
bool check(int i,int j,int k)
{
	int tmp = 1<<(j-1);
	k&=s[i];
	if ((k&tmp)!=0) return false;
	return true;
}

int dp()
{
	memset(f,0,sizeof(f));
	f[1][0][0] = 1;
	for (int i=1; i<=h[1]; i++)
		f[1][1][1<<(i-1)] = 1;
	
	for (int i=2; i<=n; i++)
	 for (int k=0; k<=i; k++)
	  for (int t=0; t<=h[i]; t++)
	   for (int last=0; last<=s[i-1]; last++) {
		//不放
		if (t==0){
			if (num[last]>k) continue;
			if (k>i-1) continue;
			f[i][k][last&s[i]] += f[i-1][k][last];
		}
		else {
			//放在t
			if (k==0) continue;
			if (num[last]>k-1) continue;
			if (check(i,t,last)) {
				int now = (last|(1<<(t-1)))&s[i];
				f[i][k][now] += f[i-1][k-1][last];
				f[i][k][now] %= oo;
			}		
		}
	   }
	for (int i=0; i<=s[n]; i++) {
		ans += f[n][K][i];
		ans %= oo;
	}
}

int main()
{
	freopen("boarda.in","r",stdin);
	freopen("boarda.out","w",stdout);
	
	scanf("%d%d",&n,&K);

	if (n<=20) {
		ans = 0;
		for (int i=1; i<=n; i++) {
			scanf("%d",&h[i]);
			s[i] = (1<<h[i])-1;
			maxh = max(maxh,h[i]);
		}
		Search_1();
		dp();
		printf("%d\n",ans);
	}
	
	fclose(stdin); fclose(stdout);
	return 0;	
}