dp斜率优化 Pearls(Hdu1300)题解

累加器传送门:

http://blog.csdn.net/NOIAu/article/details/71775000

题目传送门:

https://vjudge.net/problem/HDU-1300


题目:

In Pearlania everybody is fond of pearls. One company, called The Royal Pearl, produces a lot of jewelry with pearls in it. The Royal Pearl has its name because it delivers to the royal family of Pearlania. But it also produces bracelets and necklaces for ordinary people. Of course the quality of the pearls for these people is much lower then the quality of pearls for the royal family. In Pearlania pearls are separated into 100 different quality classes. A quality class is identified by the price for one single pearl in that quality class. This price is unique for that quality class and the price is always higher then the price for a pearl in a lower quality class.

Every month the stock manager of The Royal Pearl prepares a list with the number of pearls needed in each quality class. The pearls are bought on the local pearl market. Each quality class has its own price per pearl, but for every complete deal in a certain quality class one has to pay an extra amount of money equal to ten pearls in that class. This is to prevent tourists from buying just one pearl.

Also The Royal Pearl is suffering from the slow-down of the global economy. Therefore the company needs to be more efficient. The CFO (chief financial officer) has discovered that he can sometimes save money by buying pearls in a higher quality class than is actually needed. No customer will blame The Royal Pearl for putting better pearls in the bracelets, as long as the prices remain the same.

For example 5 pearls are needed in the 10 Euro category and 100 pearls are needed in the 20 Euro category. That will normally cost: (5+10)*10 + (100+10)*20 = 2350 Euro.

Buying all 105 pearls in the 20 Euro category only costs: (5+100+10)*20 = 2300 Euro.

The problem is that it requires a lot of computing work before the CFO knows how many pearls can best be bought in a higher quality class. You are asked to help The Royal Pearl with a computer program.

Given a list with the number of pearls and the price per pearl in different quality classes, give the lowest possible price needed to buy everything on the list. Pearls can be bought in the requested, or in a higher quality class, but not in a lower one.


输入:

The first line of the input contains the number of test cases. Each test case starts with a line containing the number of categories c (1 <= c <= 100). Then, c lines follow, each with two numbers ai and pi. The first of these numbers is the number of pearls ai needed in a class (1 <= ai <= 1000). The second number is the price per pearl pi in that class (1 <= pi <= 1000). The qualities of the classes (and so the prices) are given in ascending order. All numbers in the input are integers.


输出:

For each test case a single line containing a single number: the lowest possible price needed to buy everything on the list.


样例输入:

2
2
100 1
100 2
3
1 10
1 11
100 12


样例输出:

330
1344


这道题是斜率优化的模板题(斜率优化有模板??)

题目大意是说,有C中品质不同的Pearls,每一种品质需要买ai个,每一个的价格为pi,而你支付的价格为(ai+10)*pi,现在可以用高品质的Pearl代替低品质的,求买到所有的目标Pearls至少需要花多少钱,品质递增,pi递增


这道题看到两个递增,很容易首先想到单调队列,或者是利用单调队列的斜率优化,对于斜率优化,我在这片博文里有较为详细的讲解,如果不懂斜率优化的,可以先看这篇博客
http://blog.csdn.net/NOIAu/article/details/71774994


现在进行分析,可以很容易地想出一个dp转移方程

dp[i]=min((cnt[i]-cnt[j]+10)*p[i]+dp[j])(1<=j<i);

其中cnt是前缀和,也就是前i中珍珠一共有多少个
dp[i]表示的是,把i及之前的珍珠以某种买法,所花的最少的钱
现在进行化简
很明显

dp[i]=min(dp[j]-cnt[j]*p[i])+cnt[i]*p[i]+10*p[i];

这里的是把和i有关的东西(可以O(1)计算出而与枚举j无关的数据)提出来
所以我们只需要求dp[j]-cnt[j]*p[i]的最小值就行了
自然而然想到斜率优化


令b=dp[i],x=cnt[j],y=dp[j],k=p[i]

原来的方程 dp[i]=dp[j]-cnt[j]*p[i]转化为了

b=y-kx

转换一下,移项得到

y=kx+b

所以用单调队列斜率优化,每次记录第几个点在队列中就行了,点的坐标为(x,y)
(如果看到这里没懂的请看推荐的那篇博客,因为这里我省略了如何维护单调队列,和斜率优化是什么的讲解)
传送门:
http://blog.csdn.net/NOIAu/article/details/71774994


直接上代码

#include<iostream>
#include<cstring>
#include<cstdio>
#define MAXN 1000+10
using namespace std;

int T;

int q[MAXN];
int dp[MAXN];
int cnt[MAXN];
int p[MAXN];
int head,tail;
int n;
void init(){
    scanf("%d",&n);
    //memset(dp,0,sizeof(0));
    //memset(cnt,0,sizeof(0));
    //memset(p,0,sizeof(0));
    cnt[0]=0;
    int temp;
    for(int i=1;i<=n;i++){
        scanf("%d",&temp);
        cnt[i]=cnt[i-1]+temp;
        scanf("%d",&p[i]);
    }
    head=1;tail=2;
    dp[0]=0;
    dp[1]=(cnt[1]+10)*p[1];
    q[1]=0;
    q[2]=1;
}

void dpp(){
    for(int i=2;i<=n;i++){
        while(head<tail&&dp[q[head]]-p[i]*cnt[q[head]]>dp[q[head+1]]-p[i]*cnt[q[head+1]]) head++;
        dp[i]=dp[q[head]]-p[i]*cnt[q[head]]+cnt[i]*p[i]+10*p[i];
        int x1=cnt[i]-cnt[q[tail-1]],y2=dp[q[tail]]-dp[q[tail-1]];
        int x2=cnt[q[tail]]-cnt[q[tail-1]],y1=dp[i]-dp[q[tail-1]];
        while(head<tail&&x1*y2-x2*y1>=0){
            tail--;
            x1=cnt[i]-cnt[q[tail-1]];y2=dp[q[tail]]-dp[q[tail-1]];
            x2=cnt[q[tail]]-cnt[q[tail-1]];y1=dp[i]-dp[q[tail-1]];
        }
        q[++tail]=i;
    }
}

void print(){
    printf("%d\n",dp[n]);
}

int main(){
    scanf("%d",&T);
    while(T--){
        init();
        dpp();  
        print();
    }
    return 0;
}

这里写图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《编程珠玑》是一本经典的计算机编程书籍,由Jon Bentley所著。书中作者以宝石的形式,以自己在编程领域的经验和思考作为原料,展现了许多精彩的编程技巧和解决问题的思路。 这本书被誉为计算机界的经典之作,其价值不仅在于作者分享的个人经验,更在于其中蕴含的许多智慧和洞见。书中的每个章节都涵盖了一个独立的编程话题,包括算法优化、代码调试、程序设计等,并通过大量的实例和案例讲解了相应的技巧和方法。这些实例涵盖了几乎所有计算机领域,包括排序、查找、字符串处理等,从而帮助读者理解和掌握这些技巧。 与其他编程书籍不同,《编程珠玑》强调的是实用性和深度思考。书中的每个问题都是作者亲自经历过的,每个解决方案都是经过深思熟虑的。通过阅读这本书,读者可以学习到如何通过合理的数据结构和算法设计,将问题简化并高效解决。同时,作者还教会了读者如何思考和分析问题,如何避免一些常见的陷阱和错误。 《编程珠玑》不仅适合初级的程序员,也适合有一定编程经验的开发者阅读。无论是学习编程的初学者,还是已经有多年开发经验的工程师,都可以通过阅读这本书,提升自己的编程能力和思维方式。读者可以在书中找到灵感和启示,解决实际的编程难题,并学到一些通用的编程技巧和原则。 总之,《编程珠玑》是一本极具价值的编程书籍,其内容丰富实用,思想深入,对于提升编程能力和思维方式都具有重要意义。无论是想成为一名优秀的程序员,还是找到解决实际问题的思路,这本书都值得一读。 ### 回答2: 《编程珠玑》是由Jon Bentley于1986年出版的一本经典计算机科学书籍。书中主要讨论了各种编程问题和解决方案,旨在帮助读者提高编程技巧和思维能力。 这本书是由编程问题组成的,每个问题都来自实际编程中的实际情况。每个问题都是用C语言描述并解决的。在解决问题的过程中,书中提出了一些有趣的技巧和方法,例如位操作、动态规划、递归和分治等。这些技巧和方法不仅可以帮助我们解决具体的问题,还可以帮助我们提高编程效率和代码质量。 《编程珠玑》的作者Jon Bentley是一位计算机科学家,他在书中分享了他多年来在编程领域的经验和见解。通过这本书,读者可以学到很多关于编程的技巧和思维方式,有助于提高解决实际编程问题的能力。 总的来说,《编程珠玑》是一本非常有价值的编程书籍,无论是初学者还是有经验的程序员都可以从中受益。它可以帮助我们了解并掌握解决实际编程问题的方法和技巧,提高我们的编程能力和思维能力。如果你对编程有兴趣,并且想提高自己的编程技术,我强烈推荐你阅读这本书。 ### 回答3: 《编程珠玑》是一本由Jon Bentley编写的计算机科学经典著作,被誉为程序员必读之书。该书探讨了一系列关于编程和算法的知识和技巧,以及一些经典的编程问题和解决方法。 《编程珠玑》的主要目的是通过具体的编程案例和讨论,帮助读者提高编程技巧和解决问题的能力。书中提供了众多的编程小技巧和优化思路,让程序员能够对复杂问题进行有针对性的分析和解决。这些技巧涵盖了各个方面,包括数据结构、算法设计、性能优化等。 该书中的编程珠玑主要包括程序设计的三个重要原则:正确性、性能和可读性。作者通过讲述自己的实践经验,以及一些经典的编程问题和解决方法,来阐述这些原则。读者可以通过学习和理解这些原则,提高自己的程序设计能力,并编写出更加优秀的代码。 除了传授编程技巧和知识外,该书还强调了问题解决的思维方式。作者通过讲述一些实际问题的解决过程,鼓励读者灵活运用各种方法和工具,来解决复杂的编程难题。这种思维方式对于程序员来说非常重要,可以培养解决问题的能力,提高工作效率。 总的来说,《编程珠玑》是一本经典的计算机科学读物,通过具体的案例和讨论,帮助读者提高编程技巧和解决问题的能力。无论是想提升自己的程序设计能力,还是希望更好地解决编程难题,这本书都是值得一读的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值