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;

}

你可能感兴趣的:(PEAR)