玩具装箱(noip冲刺模拟题——DP)

来源:互联网 发布:建材价格查询软件 编辑:程序博客网 时间:2024/05/04 13:14

他人原创题,转载请务必注明出处

1.玩具装箱(toy.pas/c/cpp) Time Limit: 1000MS Memory Limit: 256M

【问题描述】

XXX喜欢玩具,家里有N个玩具,有一天,她想让玩具们晒晒太阳,XXX把所有的玩具都拿出来摆成一排,从左到右依次编号为1~N。每个玩具大小不一,玩具i的大小为Ai。

太阳下山了,XXX开始收玩具了,现在将这些玩具从左开始依次装成若干箱,每个箱子只能装最多M个且编号连续的玩具。在某个箱子里装若干个玩具的费用计算方法:如果该箱子里最大的玩具为a,最小的为b,玩具个数为s,则费用为K+s*(a-b)。这里的K是箱子本身的费用,所有箱子的费用都相等。

XXX想知道把将所有玩具都装进箱里的最小费是多少?

【输入】

第一行为3个整数N, M, K,用空格分隔。N为玩具个数,M为每个箱子最多能装的玩具个数,K为箱子本身的费用。
以下N行第i行(1<=i<=N)为整数Ai,表示第i个玩具的大小。

【输出】

输出为一个整数,表示装箱费用总和的最小值。

【输入输出样例】

toy.in
6 3 6
1
2
3
1
2
1
toy.out
21

样例解释:

第一个箱子里装玩具1~3,第二个里装4~6,开销总和为(6+3×(3−1))+(6+3×(2−1)) = 21。这是最小可能的开销总和,所以输出21。

【数据范围】

60%的数据满足:N,M<=20;

80%的数据满足:N<=2 000,M<=100;
100%的数据满足:1<=N<=20 000,1<=M<=1 000,0<=K<=1 000 000 000,
                               1<=Ai<=1 000 000 000 (1<=i<=N),M<=N

思路及代码

(数据也分享给你们 ,链接失效了可以私信或评论告诉我)

很难受,写了一个半小时只拿了20分
当模拟+数论题在写,结果发现还是要写dp
结果方程出不来,看来HSJ大佬的才知道还要先初始化(就很气)

言归正传
先把从 i 开始到 j 的最大最小值都求出来,然后把它的值也求出来
再用数组存起来
再把它当背包做,没了

但是因为它的值可能是 m*(max-min) 所以会爆int
嗯,建议把INF设为0x3fffffffffffffff (15个F,long long的最大值)

#include<cstdio>#include<algorithm>#define ll long long const ll INF=0x3f3f3f3f3f3f;using namespace std;int a[20005],n,m,k;ll f[20005],zhi[20005][1005]; //内存800兆左右,但是题目限制其实256兆int main(){       scanf("%d%d%d",&n,&m,&k);    for(int i=1;i<=n;++i) scanf("%d",&a[i]);    for(int i=1;i<=n;i++)    {        ll maxx=0,minn=INF;        for(int j=1;j<=m&&(i+j-1)<=n;j++)        {            if(a[i+j-1]>maxx) maxx=a[i+j-1];            if(a[i+j-1]<minn) minn=a[i+j-1];            zhi[i][j]=(maxx-minn)*j+k;            printf("%I64d ",zhi[i][j]);        }        printf("\n");    } //预处理    for(int i=1;i<=n;i++) f[i]=INF;    for(int i=1;i<=n;i++)      for(int j=1;j<=m&&(i-j+1)>0;j++)      f[i]=min(f[i],f[i-j]+zhi[i-j+1][j]);    printf("%I64d\n",f[n]);    return 0;}

注释也说了,这个内存超了很多
那么有没有优化呢

答案是有的(虽然是别人写的

#include <cstdio>#include <algorithm>using namespace std;const int maxn = 20005;typedef long long int64;const int64 INF = 1e18;int A[maxn],N,M,K;int64 dp[maxn];int main(){     scanf("%d%d%d", &N, &M, &K);    for(int i=1;i<=N;i++)   scanf("%d", &A[i]);    for(int i = 1 ; i <= N ; ++i){        dp[i] =INF; int mx = 0,mn = 1e9;        for(int j = i ; j > i - M  && j > 0; --j){            if(A[j] < mn) mn = A[j];            if(A[j] > mx) mx = A[j];            dp[i] = min(dp[i],dp[j-1]+(int64)(mx-mn)*(i-j+1)+K);        }    }    printf("%I64d\n",dp[N]);    return 0;}
原创粉丝点击