一道dp

链接:https://ac.nowcoder.com/acm/contest/321/L
来源:牛客网

题目描述

鸡尾酒喜欢罐子,有一天他到了一个罐子专卖店,他决定买好多好多罐子回家。但是专卖店快关门了,鸡尾酒必须尽快选购,他决定按顺序把罐子浏览一遍,如果他的钱花完了(钱数=0)或者已经走过了最后一个罐子,就会立即离开商店。

由于鸡尾酒不会掩饰自己对罐子的喜爱,所以只要他现有的钱大于等于当前看到的罐子的价格,他就会购买。

鸡尾酒有n元钱,并且想买m个罐子,你能帮他算算他应该至少带多少钱才能买到m个罐子吗?

输入描述:

第一行包含三个整数n,m,k。
n代表鸡尾酒最多能带的钱(0<=n<109),m代表鸡尾酒想买的罐子数量,k代表商店里罐子的数量,
保证商店至少有m个罐子(1<=m<=k<=300)。
接下来一行包含k个整数,第i个数表示第i个罐子的价格pi。(0<=pi<=1000)

输出描述:

输出鸡尾酒购买m个罐子至少需要带的钱数。

如果鸡尾酒无论如何都买不了m个罐子,输出 "poor chicken tail wine!"
示例1

输入

5 2 3
1 2 3

输出

3
示例2

输入

1 2 2
100 100

输出

poor chicken tail wine!

 题解:考虑到限制条件,倒着dp即可
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<queue>
 6 #include<stack>
 7 #include<set>
 8 #include<vector>
 9 #include<map>
10 #include<cmath>
11 using namespace std;
12 typedef long long ll;
13 ll a[305],dp[305][305];
14 int main()
15 {
16     ll n,m,k;
17     cin>>n>>m>>k;
18     memset(dp,0x3f3f3f3f,sizeof(dp));
19     for(int i=1;i<=k;i++)scanf("%lld",&a[i]);
20     for(int i=1;i<=k+1;i++)dp[i][0]=0;
21     for(int i=k;i>=1;i--){
22         for(int j=1;j<=k-i+1;j++){
23             if(a[i]==0&&dp[i+1][j-1]==0)dp[i][j]=min(dp[i+1][j-1]+a[i]+1,dp[i][j]);
24             else dp[i][j]=min(dp[i+1][j-1]+a[i],dp[i][j]);
25             if(a[i]>dp[i+1][j]){
26                 dp[i][j]=min(dp[i][j],dp[i+1][j]);
27             }
28         }
29     }
30     if(dp[1][m]>n)printf("poor chicken tail wine!\n");
31     else printf("%lld\n",dp[1][m]);
32     return 0;
33 }
View Code

猜你喜欢

转载自www.cnblogs.com/MekakuCityActor/p/10589317.html