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