【NYIST】暑假训练赛 (一)-----Problem B

文章通过动态规划(DP)算法解决了一个关于图书排列的问题。在有限的书籍中,小明希望将它们按照非降序排列,但只能通过将相邻的书籍装订成一册来实现。文章详细解释了如何通过DP算法最小化装订次数,并提供了具体的实现代码及样例输入输出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

整理图书

时间限制: 3000 ms  |  内存限制: 65535 KB
难度: 5
描述
小明是图书鹳狸猿,他有很多很多的书堆在了一起摆在了架子上,每摞书是横着放的,而且每摞书是订好的
是一个整体,不可分开,(可以想象架子是一条直线),但是这些书高度却参差不齐,小明有强迫症,看不得不整齐
所以他想让这些书的高度形成一个非降序列他才舒心,可是这些书是有序的,所以他只能把其中的一摞书和他相邻的书装订在一起
形成一摞新的书,那么他最少的装订次数是多少呢
输入
多组测试数据,处理到文件结束
每组数据开始有一个n(1<=n<=1000)表示有n摞书
接下来一行是这n摞书的高度a[i],(1<=a<=10^5)(虽然这个高度有点扯淡)
输出
首先输出Case num : 表示第几组数据
接下来对于每组数据输出最少的装订次数
样例输入
5
8 2 7 3 1
1
100
样例输出
Case 1: 3
Case 2: 0
提示
第一组样例:将后4本书装订在一起,共装订3次,组成8 13
第二组样例:只有一本书,无需装订
来源
CF
上传者
ACM_孙毓阳


分析:哎!做了很久,不知道自己的思路和代码哪里错了。后来,看了别人的题解,用了别人的思路才AC了,自己太菜!!!

思路:DP。


CODE:

#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;

int main()
{
    const int maxn=1005;
    int n,cnt=0;
    while(scanf("%d",&n)!=EOF){
        int high[maxn],sum[maxn],hmax[maxn];
        sum[0]=0,hmax[0]=0;
        for(int i=1;i<=n;i++){
            cin>>high[i];
            sum[i]=sum[i-1]+high[i];
            hmax[i]=max(high[i],hmax[i-1]);
        }
        int dp[maxn];
        for(int i=0;i<maxn;i++)
            dp[i]=1e6;
        dp[0]=dp[1]=0;
        for(int i=2;i<=n;i++)
            for(int j=i-1;j>=0;j--)
                if(hmax[j]<=sum[i]-sum[j]&&dp[i]>dp[j]+i-j-1){
                    dp[i]=dp[j]+i-j-1;
                    hmax[i]=sum[i]-sum[j];
                    break;
                }
        cnt++;
        cout<<"Case "<<cnt<<": "<<dp[n]<<endl;
    }
    return 0;
}

附上一直未AC:

#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;

int main()
{
    int n,cnt=0;
    while(scanf("%d",&n)!=EOF){
        int high[1005],ans=0,sum=0;
        memset(high,0,sizeof(high));
        for(int i=0;i<n;i++)
            cin>>high[i];
        for(int i=1;i<n;i++){
            sum+=high[i];
            if(sum>=high[i-1]){
                high[i]=sum;
                sum=0;
            }
            else if(sum+high[i-1]<=high[i+1]){
                high[i]=sum+high[i-1];
                sum=0;
                ans++;
            }
            else{
                high[i]=high[i-1];
                ans++;
            }
        }
        cnt++;
        cout<<"Case "<<cnt<<": "<<ans<<endl;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值