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

LA 4123 (计数 递推) Glenbow Museum

时间:2015-03-06 23:33:21      阅读:246      评论:0      收藏:0      [点我收藏+]

标签:

题意:

技术分享

这种所有边都是垂直或水平的多边形,可以用一个字符串来表示,一个270°的内角记作O,一个90°的内角记作R。

如果多边形内存在一个点,能看到该多边形所有的点,则这个多边形对应的序列是合法的。这里长度不作限制,只要长度适当能满足要求即可。

现给出序列长度,问有多少种序列符合要求。

分析:

书上分析地很清楚,罗列一下要点:

首先对于一个长度为n的合法序列,R的个数为(n+4)/2,O的个数为(n-4)/2,即R比O多4个

我们要找的序列满足要求:R比O多4个,没有两个O相邻。

这里先设计了一个O(n2)递推的状态,很好理解,看下面那个O(n)的递推

f(i, j, k)表示有i个R,有j对相邻的R,k(k=0表示R,k=1表示O)开头,R结尾的序列个数。

边界:

f(1, 0, 0) = 1,对应串R;f(1, 0, 1) = 1,对应串OR

状态转移方程:

f(i, j, k) = f(i-1, j, k) + f(i-1, j-1, k),第一个代表在最后面加OR,第二个表示在最后面加R

答案:

f((n+4)/2, 3, 0) + f((n+4)/2, 4, 1) + f((n+4)/2, 4, 0)

第一个表示开头结尾都是R的串,串中有3对相邻的R,因为串是环状的,所以首尾也算一对,共4对R

第二个是O开头,R结尾的串

第三个看起来是R开头结尾,而且中间还有4对R,但只要在最后加上一个O就行了,这样不影响R的个数,对数,总之不影响整个状态的表示。

技术分享
 1 #include <cstdio>
 2 
 3 const int maxn = 1000;
 4 
 5 long long d[maxn + 10][5][2], ans[maxn + 10];
 6 
 7 void Init()
 8 {
 9     d[1][0][1] = d[1][0][0] = 1;
10     for(int i = 2; i <= maxn; i++)
11         for(int j = 0; j < 5; j++)
12             for(int k = 0; k < 2; k++)
13             {
14                 d[i][j][k] = d[i-1][j][k];
15                 if(j) d[i][j][k] += d[i-1][j-1][k];
16             }
17 
18     for(int i = 4; i <= maxn; i+= 2)
19     {
20         int R = (i>>1) + 2;
21         ans[i] = d[R][3][0] + d[R][4][1] + d[R][4][0];
22     }
23 }
24 
25 int main()
26 {
27     Init();
28     int n, kase = 1;
29     while(scanf("%d", &n) == 1 && n) printf("Case %d: %lld\n", kase++, ans[n]);
30 }
代码君

 

LA 4123 (计数 递推) Glenbow Museum

标签:

原文地址:http://www.cnblogs.com/AOQNRMGYXLMV/p/4319369.html

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