中南大学第十一届大学生程序设计竞赛-COJ1899-Yuelu Scenes

1899: Yuelu Scenes

Submit Page Summary Time Limit: 1 Sec Memory Limit: 256 Mb Submitted: 4 Solved: 3
Description
An artist begins with a roll of ribbon, one inch wide. She clips it into pieces of various integral lengths, then aligns them with the bottom of a frame, rising vertically in columns, to form a Yuelu scene. A Yuelu scene must be uneven; if all columns are the same height, it’s a plain scene, not a Yuelu scene! It is possible that she may not use all of the ribbon.

If our artist has 4 inches of ribbon and a 2 × 2 inch frame, she could form these scenes:

She would not form these scenes, because they’re plains, not mountains!

Given the length of the ribbon and the width and height of the frame, all in inches, how many different Yuelu scenes can she create? Two scenes are different if the regions covered by ribbon are different. There’s no point in putting more than one piece of ribbon in any column.

Input
Each input will consist of several case. Each input will consist of a single line with three space-separated integers n, w and h, where n (0 n ≤ 10,000) is the length of the ribbon in inches, w (1 ≤ w ≤ 100) is the width and h (1 ≤ h ≤ 100) is the height of the frame, both in inches.

Output
Output a single integer, indicating the total number of Yuelu scenes our artist could possibly make, modulo 1e9 + 7.

Sample Input
25 5 5
15 5 5
10 10 1
4 2 2
Sample Output
7770
6050
1022
6
Hint
Source
中南大学第十一届大学生程序设计竞赛

题目大意: n1 的缎带覆盖 wh 的矩形,不能超出其范围(可以任意剪裁缎带,长度为整数),且最后覆盖的形状每一列的行高不能完全一致,总共有多少种排列方法?
解题思路: dp[i][j] 表示用了 i1 的缎带覆盖了j的宽度有多少种情况,包括行高相同的情况
dp[i][j]=dp[i][j-1]+dp[i-1][j-1]+…+dp[i-h][j-1]
但这样时间复杂度是O(nwh),是不行的
我们发现填表时,计算的是连续的一段,
故计算第j列时,统计第j-1列的前缀和sum[i]
那么

if(i-h-1>=0)  dp[i][j]=(sum[i]-sum[i-h-1])%MOD;
else          dp[i][j]=sum[i]%MOD;

每次改变列都要更新sum,
最后将行高都相等的情况减掉就可以啦~
考查内容:动态规划,前缀和优化
时间复杂度: O(nw)
题目难度: ★★★★

#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;
const int MOD=1e9+7;
LL dp[10005][105];
LL sum[10005];
int n,w,h;

void init()
{
    memset(dp,0,sizeof(0));
    memset(sum,0,sizeof(sum));
    for(int j=0;j<=w;j++)
        dp[0][j]=1;
    for(int i=0;i<=n;i++)
        dp[i][0]=1;
}

void update(int j)
{
    sum[0]=dp[0][j];
    for(int i=1;i<=n;i++)
        sum[i]=sum[i-1]+dp[i][j];
}

int main()
{
    ios::sync_with_stdio(false);
    while(cin>>n>>w>>h)
    {
        init();
        for(int j=1;j<=w;j++)
        {
            update(j-1);
            for(int i=1;i<=n;i++)
            {
                if(i-h-1>=0) dp[i][j]=(sum[i]-sum[i-h-1])%MOD;
                else dp[i][j]=sum[i]%MOD;
            }
        }
        /*cout<<endl;
        for(int i=0;i<=n;i++)
        {
            for(int j=0;j<=w;j++)
            {
                cout<<dp[i][j]<<" ";
            }
            cout<<endl;
        }*/
        if(n>=w*h) dp[n][w]-=(h+1);
        else dp[n][w]-=(n/w+1);
        cout<<dp[n][w]<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值