ZOJ 1563 Pearls(动态规划)

/*
分析:
因为他给的数据是递增的  而求得是这些数据总的 最优解
所以我们可以考虑,它的子问题求解不影响总的求解  也就是我们可以先求出 第一个的最优解  第二个....以此类推到总的最优解
那么我们想如何利用前面一个的最优解推出当前的最优解  考虑这个与背包问题类似 我们在加入当前物品时判断当前加入后是否影响到
前面的最优解
那我们就来分析 我们需要什么要的数据
因为题目中计算最优解的时候每个等级的Money是固定的  而我们的每个等级所需要买的珍珠数量是不一定的 我的记录最优解的状态是记录
前n个等级所得出来的最优解。 
则可以确定的是 Money[max],dp[max]是需要的。接下来是分析(每个等级所需要买的珍珠数量是不一定)
因为我们是根据前n等级的最优解就是前n等级下的花的最少的钱 我们知道的是当前等级的数量和价格 
我们想知道的是用当前等级的价格去买该等级以下的珍珠是否比前面的解法更优 而如果用遍历用当前等级的价格买该等级以下的所有情况。
这些情况我们列举一下 就是1...n ,2..n,3....n,...,n-1...n;所需要知道的就是这些阶段的珍珠数量。而我们可以用sum[i]记录前i个的所有珍珠,获得
想要阶段的珍珠数量只需要sum[n]-sum[i]就可以了 。
分析到这里我们就可以写动态方程了。 dp

for(i=1;i<=n;i++) dp[i]=1000000;
for(j=0;j<i;j++)
动态方程就是 dp[i]=min(dp[i],dp[j]+(sum[i]-sum[j]+10)*money[i]);
*/
#include<iostream>
#include<cstring>
#include<algorithm>
#include<climits>
using namespace std;
int sum[101],money[101];
int dp[101];
int main(void)
{
    int t,n,j;
    cin>>t;
    while(t--)
    {
        cin>>n;
        memset(dp,0,sizeof(dp));
        sum[0]=0;
        for(int i=1;i<=n;i++)
        {
            cin>>j>>money[i];
            sum[i]=sum[i-1]+j;
        }
        for(int i=1;i<=n;i++)
        {
            dp[i]=INT_MAX;
            for(j=0;j<i;j++)
            {
                dp[i]=min(dp[i],dp[j]+(sum[i]-sum[j]+10)*money[i]);
            }
        }
        cout<<dp[n]<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/woshijishu3/p/4185670.html