UVALive - 8291 Pavers

转自:https://blog.csdn.net/lingyan_BVB/article/details/80172102

Pavers

时间限制: 1 Sec  内存限制: 128 MB

题目描述

In the land of Quendor, walkways, sidewalks and hallways are always 2 mb (mini-bloit, roughly  1/2000  of a bloit) in width.  J. Pierpont Flathead (pictured below) has hired the Frobozz Magic Paver Company to install new walkways in and around all his banks using pavers.  Given the huge number of walkways found at each bank, and the eccentricity of Flathead, Frobozz decided to write a program to determine how many different ways there are to completely cover a walkway using pavers that are 1mb-by-1mb squares, 2mb-by-1mb rectangles in either orientation and right (or L-shaped) tromino pavers in any of the four possible orientations shown below.  This list would then be presented to Flathead so he could choose the patterns he wanted. 

You will help write this program for Frobozz.  Your program must find the total number of tilings and the total number of each paver type used in those tilings.  For instance, there are two tilings of a 2-by-1 walkway using a total of two 1-by-1 square pavers and one 2-by-1 rectangular paver. 

For a 2-by-2 rectangle, there are 11 tilings using a total of 16 1-by-1 square pavers, 8 2-by-1 rectangular pavers and 4 tromino pavers. 

Write a program which takes as input the length n (in mb) of a 2-by-n walkway and outputs the number of tilings by combinations of the three paver types as well as the total number of each type of paver used. 

输入

The first line of input contains a single decimal integer P, (1≤P≤10000), which is the number of data sets that follow.  Each data set should be processed identically and independently. 
Each data set consists of a single line of input.  It contains the data set number, K, followed by a single space, followed by the decimal length n of the walkway.  Values of n will be chosen so that all of the output values will fit in a 32 bit unsigned integer. 

输出

For each data set there is one line of output.  The output line consists of the five decimal integers separated by a single space:  the data set number, K followed by the total number of tilings of a 2-by-n walkway, the total number of 1-by-1 square pavers used, the total number of 1-by-2 rectangular pavers used and the total number of tromino pavers used for these tilings. 

样例输入

2
1 1
2 2

样例输出

1 2 2 1 0
2 11 16 8 4

题目大意:给你个2*n的格子,给你三种地板,旋转后得到如下图所示的几种地板,让你铺满整个格子,问对每个给定的n有多少种铺法,这些方法一共会用掉三种地板各多少块。(保证输出都在无符号整形之内)

思路:n==1和n==2时的结果手酸就可以,从n==3开始我们就可以找到规律:

    1、首先是最明显的,n可以从n-1转化而来,转化的方案无非只有两种:

    2、其次我们发现,n也可以从n-2转化而来,转化的方案有七种(去掉会和从n-1转化而来重复的)(画圈的为未重复的):

    3、n同样可以从n-i转化而来(2<=i<=n),这时我们分类讨论:

           ①i%2==1的情况:不会画图,画图丑见谅......这里以i==3为例。当i>3时情况类似,只是在中间加了两个1*2的地板(对左边六个来说,加的两个1*2地板分插在了L型板边上,上下两层各一个;对右边两个来说,加的地板在本来的1*2的地板与1*1的地板之间)。

           ②i%2==0的情况:这里是以i==4为例的,当i>4时情况也类似,也是在中间加两块1*2的地板,加地板的方法与i%2==1时的情况类似,就不再赘述了。

然后利用这几条规律写出方法数以及三种地板用量的递推关系,暴力打表后发现n最多到15,n==16时所用的1*1的地板数就爆了unsigned int了,所以打表到15这道题就没问题了......

最后附上代码:

#include <bits/stdc++.h>
struct node
{
    long long f,a,b,c; //f为方法数,a为1*1的地板数,b为1*2的地板数,c为L形的地板数
};
node z[16];
int main()
{
    int p,k,n,i,j;
    scanf("%d",&p);
    z[1].f=z[1].a=2;
    z[1].b=1;
    z[1].c=0;
    z[2].f=11;
    z[2].a=16;
    z[2].b=8;
    z[2].c=4;
    z[0].f=1;   //以上均为初始化,其实是懒得考虑越界情况了....
    for (i=3;i<=15;i++)   //f,a,c均用我们得到的递推关系写出
    {
        z[i].f=z[i-2].f*7+z[i-1].f*2;
        for (j=3;j<=i;j++)
            z[i].f+=8*z[i-j].f;
        z[i].a=z[i-1].a*2+z[i-2].a*7+z[i-1].f*2+z[i-2].f*8;
        for (j=3;j<=i;j++)
            z[i].a+=8*(z[i-j].f+z[i-j].a);
        z[i].c=z[i-1].c*2+z[i-2].c*7+z[i-2].f*4;
        for (j=3;j<=i;j++)
            z[i].c+=8*(z[i-j].f+z[i-j].c);
        z[i].b=(z[i].f*2*i-z[i].a-z[i].c*3)/2;    //1*2的地板数懒得算了...直接用面积减去其他两种地板所占的面积来求
    }
    while (p--)
    {
        scanf("%d%d",&k,&n);
        printf("%d %lld %lld %lld %lld\n",k,z[n].f,z[n].a,z[n].b,z[n].c);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值