HDOJ1300

刷题时间:2019/4/16

hdoj1300题目大意:

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1300

一个老哥要买珍珠,然后又想要花最少的钱买珍珠,然后珍珠卖家很奇怪,在每次买一种珍珠的时候为了防止你买的少就要加上十个数量作为手续费,然后这个老哥就想了一个方法,可以用高等级的珍珠来充当低等级的珍珠,然后输入的珍珠后面的是高等级的 前面是低等级的,意思就是可以用后面的珍珠来充当前面的珍珠,使之让总共花的钱最少。

从这个题目大意 我们就能得出 这是一个简单明显的dp 的题

我们只需要建一个dp[i]数组,用来表示买i个珍珠需要的最少金钱 

废话不多说:  状态转移方程: 初始化dp[1]=(see[1]+10)*b[1] 表示买第一个等级需要花的钱

see数组表示前面i个种类珍珠的总共数量 这里用到了前缀和 see[i]=see[i-1]+a[i]  后面我会详细的讲解一下前缀和

前缀和 其实也没什么神奇的  就是能在O(1) 的复杂度下 求出在一个序列中第i个到第j个数的和 sum[j]-sum[i]

扯远了..... 不好意思

状态转移方程: dp[i]=min(dp[i],dp[j]+(see[i]-see[j]+10)*b[i]) 这里see[i] 表示的是前i种的总数 see[j]是从1到i 进行查找是否存在把低等级珍珠换成高等级的珍珠使之总花费dp[i] 更低的出现 有就更新

有了状态转移方程就方便啦  最后dp[n] 就表示第n种需要花的最少钱

代码如下

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define db double
#define MAX 100000
#define rep(i,j,k) for(int i=(int)(j);i<=(int)(k);i++) 
#define per(i,j,k) for(int i=(int)(j);i>=(int)(k);i--)
int a[MAX],b[MAX];
int dp[MAX * 2];
int see[MAX];
void solve()
{
	int c;
	cin >> c;
	memset(see, 0, sizeof(see));
	rep(i, 1, c) {
		cin >> a[i] >> b[i];
		see[i] = see[i - 1] + a[i];
	}
	//初始化 第一行都是全部买本质量的珍珠
	dp[1] = (see[1] + 10)*b[1];
	rep(i, 2, c) {
		dp[i] = (see[i] + 10)*b[i];
		rep(j, 1, i-1) {
			dp[i] = min(dp[i], dp[j] + (see[i] - see[j]+10)*b[i]);
			//让前面的 see[i-1]-see[j]的全部数量用b[i] 的价格买
		}
	}
	cout << dp[c] << endl;
}
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		solve();
	}
	//system("pause");
	return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值