码迷,mamicode.com
首页 > 其他好文 > 详细

COJ 0260 HDNOIP201204四个国王

时间:2015-07-10 22:12:39      阅读:306      评论:0      收藏:0      [点我收藏+]

标签:

HDNOIP201204四个国王
难度级别:A; 运行时间限制:1000ms; 运行空间限制:51200KB; 代码长度限制:2000000B
试题描述

    在N*M的棋盘上摆国际象棋中的“国王”。如果两个“国王”占据的格子有公共边或者公共顶点,那么他们就会相互攻击。现在想知道,一共有多少种不同的方法摆上K个互不攻击的国王呢?

输入
第一行包含三个整数,分别表示N、M和K。
输出
输出一个整数,表示方法数。若超过2147483647,你只用输出2147483648即可。
输入示例
样例输入1
3 3 4

样例输入2
5 100 50
输出示例
样例输出1
1

样例输出2
2147483648
其他说明
第一个样例只有一种可能:
XOX
OOO
XOX
X表示一个国王,O表示一个空格子。
第二个样例的方法数显然多于2147483647。

对70%的数据,N<=5,M<=5,0<=K<=4,
对另外30%的数据,N<=5,M<=100,0<=K<=N*M

题解:妈妈呀好题!

"n小思状压,网格用层次",所以很容易得出DP:f[i][j][k]表示前i列放j个国王且第i列状态为a[k]的放法总数

转移:f[i][j][k]=sum(f[i-1][j-b[s_now]][s_think]) (j∈ok_set)

那么肿么求ok_set呢?暴力init就行,如果追求完美可以打表哦~

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<cstring>
 7 #define PAU putchar(‘ ‘)
 8 #define ENT putchar(‘\n‘)
 9 using namespace std;
10 const int maxn=100+10,maxm=500+10,maxs=15,maxt=13,inf=-1u>>1;
11 long long f[maxn][maxm][maxs],sum;
12 int a[maxt]={0,1,2,4,5,8,9,10,16,17,18,20,21},b[maxt]={0,1,1,1,2,1,2,2,1,2,2,2,3},p[6]={0,2,3,5,8,13};
13 int w[5]={1,2,4,8,16},c,n,m,k;bool g[maxt][maxt];
14 inline int read(){
15     int x=0,sig=1;char ch=getchar();
16     while(!isdigit(ch)){if(ch==-)sig=-1;ch=getchar();}
17     while(isdigit(ch))x=10*x+ch-0,ch=getchar();
18     return x*=sig;
19 }
20 inline void write(int x){
21     if(x==0){putchar(0);return;}if(x<0)putchar(-),x=-x;
22     int len=0,buf[15];while(x)buf[len++]=x%10,x/=10;
23     for(int i=len-1;i>=0;i--)putchar(buf[i]+0);return;
24 }
25 void init(){
26     n=read();m=read();k=read();
27       if(!k||n<=0||m<=0){write(0);return;}
28       for(int i=0;i<p[n]-1;i++)
29         for(int j=i+1;j<p[n];j++){
30             if(a[i]&a[j]) continue;
31             int d;for(d=0;d<5;d++)if(w[d]&a[i]){
32                   if(d<4&&(w[d+1]&a[j]))break;
33                   if(d>0&&(w[d-1]&a[j]))break;
34                 }if(d>4)g[i][j]=g[j][i]=true;
35             }g[0][0]=true;
36       for(int i=0;i<p[n];i++)f[1][b[i]][i]=(b[i]<=k);
37     return;
38 }
39 void work(){
40     for(int i=2;i<=m;i++)
41         for(int j=0;j<=k;j++)
42               for(int c=0;c<p[n];c++)
43                 for(int d=0;d<p[n];d++)if(g[c][d]&&j>=b[c])
44                     f[i][j][c]+=f[i-1][j-b[c]][d];
45     return;
46 }
47 void print(){
48     for(int j=0;j<p[n];j++){
49         sum+=f[m][k][j];
50         if(sum>inf){puts("2147483648");return;}
51     }write(sum);
52     return;
53 }
54 int main(){init();work();print();return 0;}

 

COJ 0260 HDNOIP201204四个国王

标签:

原文地址:http://www.cnblogs.com/chxer/p/4637586.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!