购物

购物

https://ac.nowcoder.com/acm/problem/14526

购物

https://ac.nowcoder.com/acm/problem/14526

题意:n * m个糖果,每个糖果都有价格,小明需要花最少的钱保证每天都有糖果吃,而且每天不能购买超过m个糖果,每天买第j个糖果的价格是a[i][j]+j*j,问你最少花多少钱过n天?

思路:首先想到对每天的价格排序,贪心去取小的,但是你可能这一天相对于后几天都比较小,那我们该怎么办?n<=300 dp转移?显然可以🤣 复杂度O(n^3),挺好写的,不详细解释了,读者可以尝试这个思路完成,dp[i][j]表示第i天买了j个糖果的最小花费。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>p;
const int N=305;
int dp[N][N],sum[N][N],a[N][N];
int n,m;
int main() {
    cin>>n>>m;
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=m; j++) {
            scanf("%d",&a[i][j]);
        }
        sort(a[i]+1,a[i]+m+1);
        for(int j=1; j<=m; j++)
            sum[i][j]=sum[i][j-1]+a[i][j];
    }
    memset(dp,63,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<=min(j,(i-1)*m); k++) {
                dp[i][j]=min(dp[i][j],dp[i-1][k]+sum[i][j-k]+(j-k)*(j-k));
            }
        }
    }
    printf("%d\n",dp[n][n]);
}

考虑O(n^2log)的做法,
因为每天我们都按照价格从低到高买糖果,排完序之后如果我们第i天买了第x个糖果,前
x-1个是肯定要买的——只买前x-1个糖果花了sum[i][x-1] + (x-1)^2的钱,买前x个糖果花sum[i][x] + x^2的钱,相减就会发现买第x个糖果的钱为a[i][x]+2x-1(相当于把附加的钱按照贡献分给每个糖果),其实只和他自己的价格以及在自己那一天是第几个买有关,和他前面的糖果都是多少钱无关,且原来排在花钱少的糖果最终花钱还是少(如果我们选了第x个糖果那么他前面的糖果肯定都选上了)。这样,最后吃掉的n个糖果一定是a[i][x]+2x-1最小的n个(真正买的时候不是按照大小关系顺序而是按照日期),所以直接贪心就可以了——先把每天的糖果排序,排好之后给他们加上排位带来的附加价格(2x-1),然后按照加上了附加价格之后的价格把每天可以买的糖果放入容器里,再把容器中价格最小的糖果拿出来(这个容器可以用堆也可以用set等)。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>p;
const int N=305;
int dp[N][N],sum[N][N],a[N][N];
int n,m;
int main() {
    cin>>n>>m;
    int ans=0;
    multiset<int>s;
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=m; j++) {
            scanf("%d",&a[i][j]);
        }
        sort(a[i]+1,a[i]+m+1);
        for(int j=1; j<=m; j++)s.insert(a[i][j]+2*j-1);
        ans=ans+*s.begin();
        s.erase(s.begin());
    }
    printf("%d\n",ans);
}
全部评论
兄弟你第一个Dp代码好像也错,你可以跑一下这组数据: 7 5 174 303 346 131 219 170 13 475 322 84 130 464 469 417 21 11 446 176 447 24 166 339 277 275 180 440 47 263 180 408 279 43 281 216 339 答案是299 错在第三重循环k应该从max(i-1,j-m)开始才对
点赞 回复 分享
发布于 2020-08-25 17:48

相关推荐

野猪不是猪🐗:😇:恭喜你以出色的表现成为xxx的一员 😨:您以进入本公司人才库 实际点开:您愿望单中的xxx正在特卖!
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务