题意: 小需要储备
天的面包,面包店每天生产
个面包,第
天生产的第
块面包的价格为
,同时,一天购买
块面包需要额外花费
,现在问储备至少
块面包的最低价格是多少。
数据范围:
题解:
分组背包问题。从低价到高价开始选择面包,本题关键是考虑额外的部分。
考虑第天的第
块面包,需要多加
,对于第
块面包,需要多加
,所以对于第
块面包多的价值就是
。所以预处理下第
天的前缀和即可。同时要考虑到每天得有面包吃,所以转移时前一个状态必须从
开始。
时间复杂度:
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; template<typename T> inline T Read() { T x = 0, f = 1; char ch = getchar(); while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();} while(isdigit(ch)) {x = (x << 3) + (x << 1) + ch - '0'; ch = getchar();} return x * f; } #define read() Read<int>() #define readl() Read<long long>() const int N = 310; int f[N][N]; int c[N][N]; int main() { int n = read(), m = read(); for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) c[i][j] = read(); sort(c[i] + 1, c[i] + 1 + m); c[i][0] = 0; for(int j = 1; j <= m; j++) c[i][j] += c[i][j - 1] + (2 * j - 1); } memset(f, 0x3f, sizeof f); f[0][0] = 0; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) for(int k = max(i - 1, j - m); k <= j; k++) f[i][j] = min(f[i][j], f[i - 1][k] + c[i][j - k]); printf("%d\n", f[n][n]); return 0; }