牛客练习赛7:B-购物 (dp)

来源:互联网 发布:黑苹果mac os安装教程 编辑:程序博客网 时间:2024/06/08 10:14

题目链接:https://www.nowcoder.com/acm/contest/38/B


题目描述:

给出N,M,有N天,每天店里都生产M颗糖果,这N天要去商店买

糖果,但是有一个条件,如果某天买的糖果数是K个,则需要额外

花费K*K的钱,而且要保证每天都有糖果吃。问购物的最小花费。


解题思路:

贪心+dp.

从题目中提取信息。每天都要买糖果吃,则前i天买的糖果数量

至少是i,而且最少买N颗糖果就可以满足条件,为了使花钱最少,

某天买k件的话,希望是当天糖果的前k小。所以对于每天给出的

M个糖果,按价格从小到大排序。这样就能计算出某天买K件的最

小花费。然后设立数组,dp[i][j]代表的含义是前i天至少买j件的最

小花费。由于前i天至少买i个,所以对于前i天,j的范围是从i~N,

然后我们可以枚举第i天买多少件,然后其状态可以由前i-1天买

糖果数得来。由于第1天必须买,而剩余N天可以有买的情况,

和不买的情况,所以可以把第一天抽出来考虑。

比赛的时候我没有把第一天单独抽出来,导致思路极度混乱,

我来我就单独处理第一天,其他的都按他们的条件处理,然后

就直接交过了,真的应该早点把他抽出来。


AC代码:

#include <iostream>#include <stdio.h>#include <algorithm> using namespace std; const int inf = 0x3f3f3f3f;const int maxn = 305;int dp[maxn][maxn];     ///dp[i][j]前i天买j件的最少花费int temp[maxn];         ///临时存放第i天糖果价格的数组int price[maxn][maxn];  ///price[i][j]第i天买j件的最小花费///需要N天,则需要N个糖果int main() {    int N,M;    while(~scanf("%d%d",&N,&M)) {        for(int i = 1; i <= N; i++) {            for(int j = 1; j <= M; j++) {                scanf("%d",&temp[j]);            }            sort(temp+1,temp+1+M);  ///对每组价格排序            price[i][0] = 0;            for(int j = 1; j <= M; j++) {                price[i][j] = price[i][j-1]+temp[j]-(j-1)*(j-1)+j*j;            }        }        int Max = max(M,N);        for(int i = 0; i <= N; i++) {            for(int j = 0; j <= Max; j++) {                    if(i == 0)                        dp[i][j] = 0;                    else                        dp[i][j] = inf;            }        }        /**由于每天必须有糖果吃,因此第1天必须买,        而剩余几天可能买,可能不买,第一天与其他        天情况考虑不一致,单独抽出来求**/        for(int j = 1; j <= M; j++) {            dp[1][j] = price[1][j];        }        for(int i = 2; i <= N; i++) {           ///前i天买k个糖果,由于前i天至少买i个糖果,所以k>=i           for(int k = N; k >= i; k--) {                ///枚举第i天买了多少糖果,前i-1天至少买i-1个糖,所以k-j>=i-1                for(int j = 0; j <= M; j++) {                    if(k-j >= i-1) {                        dp[i][k] = min(dp[i][k],dp[i-1][k-j]+price[i][j]);                    }                }           }        }        printf("%d\n",dp[N][N]);    }    return 0;}


原创粉丝点击