ACM: uva 1073 - Glenbow Museum

Glenbow Museum

The famous Glenbow Museum in Calgary is Western Canada's largest museum, with exhibits ranging from art to cultural history to mineralogy. A brand new section is being planned, devoted to brilliant computer programmers just like you. Unfortunately, due to lack of space, the museum is going to have to build a brand new building and relocate into it.

The size and capacity of the new building differ from those of the original building. But the floor plans of both buildings are orthogonal polygons. An orthogonal polygon is a polygon whose internal angles are either 90° or 270°. If 90° angles are denoted as R (Right) and 270° angles are denoted as O (Obtuse) then a string containing only R and O can roughly describe an orthogonal polygon. For example, a rectangle (Figure 1) is the simplest orthogonal polygon and it can be described as RRRR (the angles are listed in counter-clockwise order, starting from any corner). Similarly, a cross-shaped orthogonal polygon (Figure 2) can be described by the sequence RRORRORRORRO, RORRORRORROR, or ORRORRORRORR. These sequences are called angle strings.

ACM: <wbr>uva <wbr>1073 <wbr>- <wbr>Glenbow <wbr>Museum

 

Of course, an angle string does not completely specify the shape of a polygon -- it says nothing about the length of the sides. And some angle strings cannot possibly describe a valid orthogonal polygon (RRROR, for example).

To complicate things further, not all orthogonal polygons are acceptable floor plans for the museum. A museum contains many valuable objects, and these objects must be guarded. Due to cost considerations, no floor can have more than one guard. So a floor plan is acceptable only if there is a place within the floor from which one guard can see the entire floor. Similarly, an angle string is acceptable only if it describes at least one acceptable polygon. Note that the cross-shaped polygon in Figure 2 can be guarded by someone standing in the center, so it is acceptable. Thus the angle string RRORRORRORRO is acceptable, even though it also describes other polygons that cannot be properly guarded by a single guard.

Help the designers of the new building determine how many acceptable angle strings there are of a given length.

Input 

The input file contains several test cases. Each test case consists of a line containing a positive integer L (1 L 1000) , which is the desired length of an angle string. The input will end with a line containing a single zero.

Output 

For each test case, print a line containing the test case number (beginning with 1) followed by the number of acceptable angle strings of the given length. Follow the format of the sample output.

Sample Input 

4

6

0

Sample Output 

Case 1: 1

Case 2: 6

 

题意: Glenbow博物馆要建直角多边形的地面, 要求这个多边形有一个点可以看到边界上每一个点. 并且

      地面每个90度的内角就标记为R, 每个270度的内角标记为O, 现在给定一个L长度的RO序列, 问你

      有多少种可能满足地面序列.

 

解题思路:

      1. 你画一画就会发现, 每个270度的内角对应一个90度内角, 而且90度内角会在多出4个. 假设

         多边形的内角个数(序列长度)为n, 90度(n+4)/2个;, 270度(n-4)/2个, 并且n< 3且n为奇数

         不可能满足条件.

      2. 假设现在一个多边形内部存在一个点, 可以看到整个多边形的点, 那么它的上下左右的四条边

         一定是RR, 并且相邻的两条RR边之间一定存在OROROR...这样的序列(边);

      3. 序列内一定不会出现OO这样的边, 问题就转化为: (n+4)/2个R, (n-4)/2个O的环状序列, 并且

         其中没有OO相邻, 有多少种序列.

         设状态: dp[i][j][k][p]表示i个R, j个O, 第一个元素是R(k=0)或O(k=1), 最后一个元素R(p=0)

         或O(p=1)的序列种数.

         边界条件: dp[i][0][0][0] = dp[0][1][1][1] = 1;

         状态方程: dp[i][j][k][0] = dp[i-1][j][k][0]+dp[i-1][j][k][1];

                   dp[i][j][k][1] = dp[i][j-1][k][0];

         结果: dp[(n+4)/2][(n-4)/2][0][0]+
               dp[(n+4)/2][(n-4)/2][0][1]+
               dp[(n+4)/2][(n-4)/2][1][0])

 

代码:

#include
#include
#include
using namespace std;
#define MAX 1005
typedef long long ll;

int n;
ll dp[MAX][MAX][2][2];

void init()
{
 memset(dp, 0, sizeof(dp));
 dp[0][1][1][1] = 1;
 for(int x = 1; x <= 1000; ++x)
  dp[x][0][0][0] = 1;

 for(int i = 1; i <= 1000; ++i)
 {
  for(int j = 1; j <= 1000; ++j)
  {
   dp[i][j][0][0] = dp[i-1][j][0][0]+dp[i-1][j][0][1];
   dp[i][j][1][0] = dp[i-1][j][1][0]+dp[i-1][j][1][1];
   dp[i][j][0][1] = dp[i][j-1][0][0];
   dp[i][j][1][1] = dp[i][j-1][1][0];
  }
 }
}

int main()
{
// freopen("input.txt", "r", stdin);
 init();
 int num = 1;
 while(scanf("%d", &n) != EOF)
 {
  if(n == 0) break;

  if(n < 4 || n%2 == 1) printf("Case %d: 0\n", num++);
  else
  {
   printf("Case %d: %lld\n", num++,
    dp[(n+4)/2][(n-4)/2][0][0]+
    dp[(n+4)/2][(n-4)/2][0][1]+
    dp[(n+4)/2][(n-4)/2][1][0]);
  }
 }

 return 0;
}

你可能感兴趣的:(ACM)