人生不当平平淡淡。
题意:
一个公司卖的珍珠分为c个档次,价格从低到高都不相同,且同一档次的所有珍珠价格相同,由于经济衰退,每买一种珍珠都必须多花10个该档次珍珠的钱,同时,你可以把低档次的珍珠当成高档次的珍珠购买,以此避免购买低档次珍珠必须多花的10个珍珠的价格。已知你需要采购的各种珍珠的数量,求最少花费多少钱。
Input
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.
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.
Output
For each test case a single line containing a single number: the lowest possible price needed to buy everything on the list.
典型DP,模型建立了好久才搞定,dp[i][j],i表示计算到了哪一种珍珠,j表示到当前珍珠种类为止有多少枚珍珠没有付款(即想要放到更高档次去付,包括当前种类),所以就有三种情况:
对0<j<a[i],dp[i][j]=inf;
对j>=a[i],dp[i][j]=dp[i-1][j-a[i]](当前种类计算时有没付款的珍珠,则当前种类珍珠必然不付款,这是局部的贪心性质);
对j==0,dp[i][j]=min(dp[i-1][j]+(j+10)*p[i]);
此题空间限制10^4KB,换算成int的数量是10^6级别,dp数组大小为c*c*a,刚好为10^7级别,上滚动数组解决。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
#define mxn 110
#define mxm 100010
#define inf 0x3f3f3f3f
int a[mxn],p[mxn];
int n;
int dp[2][mxm];
int main(){
int cs;
scanf("%d",&cs);
while(cs--){
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d%d",&a[i],&p[i]);
memset(dp,0x3f,sizeof(dp));
dp[0][0]=0;
int sum=0;
for(int i=1;i<=n;++i){
sum+=a[i];
for(int j=0;j<a[i];++j)
dp[i%2][j]=inf;
for(int j=a[i];j<=sum;++j)
dp[i%2][j]=dp[(i+1)%2][j-a[i]];
for(int j=1;j<=sum;++j)
dp[i%2][0]=min(dp[i%2][0],dp[i%2][j]+(j+10)*p[i]);
}
printf("%d\n",dp[n%2][0]);
}
return 0;
}