1. 程式人生 > 實用技巧 >牛客等級之題N1(8.4場) 購物(dp動態規劃)

牛客等級之題N1(8.4場) 購物(dp動態規劃)

題目連結:https://ac.nowcoder.com/acm/contest/6877/A

題目描述

在遙遠的東方,有一家糖果專賣店。 這家糖果店將會在每天出售一些糖果,它每天都會生產出m個糖果,第i天的第j個糖果價格為C[i][j]元。 現在的你想要在接下來的n天去糖果店進行選購,你每天可以買多個糖果,也可以選擇不買糖果,但是最多買m個。(因為最多隻生產m個)買來糖果以後,你可以選擇吃掉糖果或者留著之後再吃。糖果不會過期,你需要保證這n天中每天你都能吃到至少一個糖果。 這家店的老闆看你經常去光顧這家店,感到非常生氣。(因為他不能好好睡覺了)於是他會額外的要求你支付點錢。具體來說,你在某一天購買了 k 個糖果,那麼你在這一天需要額外支付 k2
的費用。

那麼問題來了,你最少需要多少錢才能達成自己的目的呢?

輸入描述:

第一行兩個正整數n和m,分別表示天數以及糖果店每天生產的糖果數量。
接下來n行(第2行到第n+1行),每行m個正整數,第x+1行的第y個正整數表示第x天的第y個糖果的費用。

輸出描述:

輸出只有一個正整數,表示你需要支付的最小費用。

輸入

3 2 
1 1
100 100 
10000 10000

輸出

107

輸入

5 5
1 2 3 4 5
2 3 4 5 1 
3 4 5 1 2 
4 5 1 2 3 
5 1 2 3 4

輸出

10

題意:輸入一個n*m的價格矩陣,表示第i天的第j個糖果的價格,我們從中選取n個,價格最低,輸出最低價格,但是我們在一天購買k個糖果就要多交k*k元。

比如樣例1的第一天,我們買2個糖果,那就要多交4元,即6元買了2個糖果,第二天我們花101買1個糖果,合計107;此外我們還要保證每一天都要有糖果吃,即第一天是肯定必須要買的

題解:初看模擬貪心,直接找最少的值,後發現模擬不出來,他可以有很多個最少的值,我們要考慮哪天買幾個,這個就比較複雜了。然後才想到dp。

我們用dp[ i ][ j ]表示 第i天 買了j個糖果的最低價格。k列舉第i天買了k個;

這裡的a[ i ][ j ]我們先預處理字首和,那樣直接加的是j-k個糖果的價格。

轉移狀態 dp[ i ][ j ] = min ( dp[ i ] [ j ] , dp [ i-1 ] [ k ] + a[ i ] [ j - k ] +( j-k )*( j-k ) )

#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=300+7;
const ll mod =998244353;
int t,n,m;
int ma[maxn][maxn];
int dp[maxn][maxn];
int main(){
    IOS
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&ma[i][j]);
        }
        sort(ma[i]+1,ma[i]+m+1);
        for(int j=1;j<=m;j++){
            ma[i][j]+=ma[i][j-1];
        }
    }
    memset(dp,inf,sizeof(dp));
    dp[0][0]=0;
    for(int i=1;i<=n;i++){
        for(int j=i;j<=min(i*m,n);j++){
            for(int k=i-1;k<=j;k++)
            dp[i][j]=min( dp[i][j], dp[i-1][k]+ma[i][j-k]+(j-k)*(j-k)   );
        }
    }
    printf("%d\n",dp[n][n]);
    return 0;
}