pku 1260 Pearls 简单DP

http://poj.org/problem?id=1260

题意是:给定不同级别不同价值的珍珠,问如果购买所有的珍珠最少花费。每买一种价格的珍珠就要多付10个钱。其中低等的珍珠可以用高等的珍珠进行替代

才开始自己想的是对于当前等级i的珍珠要么只买这一等级的珍珠,要么用这一等级的珍珠替换所有比他低级的珍珠以求得购当前(a[1]+a[2]+a[3] +....+a[i])数量珍珠的最少费用,样例过了可是WA后来想了想对于当前状态比他低级的不应定非要用它替换,我们只要最小就可以了,如果这要对于i后面的状态(情况特别多)就不好处理了。最后看了一下discuss有人证明了,只要枚举比i低级的连续的等级用i替换求出最小就可以了。

 状态转移方程dp[i] = min(dp[i] ,dp[j] + (p[j].ai + p[j + 1].i + ..... + p[i].ai + 10)*p[i].pi) (0<= j <=i) dp[i]表示购买前i个等级的所有珍珠的最少花费

证明如下:

首先证明最优解中肯定不会有交叉的替换,即在质量为a<b<j<c<d的情况下,如果a被c替换,那么b也一定要被c替换 假设在最优解中存在:a被c替换且b不被c替换的情况:
1.b不被任何替换 那么此时把a换成用b替换 得到比原来更优的解,错误
2.b被j替换,此时把a换成用j替换 得到比原来更优的解,错误
3.b被d替换,此时把b换成用c替换 得到比原来更优的解,错误
因此,不存在交叉的替换,
View Code
#include <iostream>
#include <cstring>
#include <cstdio>
#define maxn 107
#define inf 99999999
using namespace std;

int c;
struct node
{
    int ai;
    int pi;
}p[maxn];
int dp[maxn];
int main()
{
    //freopen("in.txt","r",stdin);
    int t,i,j;
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d",&c);
        for (i = 1; i <= c; ++i)
        scanf("%d%d",&p[i].ai,&p[i].pi);
        for (i = 0;i <= c; ++i)
        dp[i] = inf;
        dp[0] = 0;
        for (i = 1; i <= c; ++i)
        {
            int sum = p[i].ai;
           for (j = i - 1; j >= 0; --j)
           {
               dp[i] = min(dp[i],dp[j] + (sum + 10)*p[i].pi);
               sum += p[j].ai;
           }
        }
        printf("%d\n",dp[c]);
    }
    return 0;
}
posted @ 2012-04-29 13:26  E_star  阅读(220)  评论(0编辑  收藏  举报