hicocoder#1965 : 生存游戏(优先队列)

时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
小Hi在玩一款生存游戏。他需要在游戏中成功活过N个夜晚才能通关。而每一天的夜晚都会有僵尸攻击,其中第i天的攻击会消耗Ai个生存物资。换句话说,如果在第i天的夜晚小Hi剩余的生存物资少于Ai个,游戏就会失败。

获得生存物资的唯一方式是从商人NPC处购买。每一天白天商人都会出售M个生存物资(前一天没卖出的物资不会再卖)。不过这些物资价格不同,具体来说,第i天出售的第j个生存物资的价格是Pij枚金币。

特别地,由于小Hi选择的是地狱难度,游戏还会对大量购买生存物资做出惩罚。具体来说,如果小Hi在某一天一共买了K个生存物资,他还需要额外支付 K 2 K^2 K2枚金币的惩罚。

请你帮助小Hi计算,要通关游戏至少需要多少枚金币?

输入
第一行包含两个整数N和M。

第二行包含N个整数,A1, A2, A3, … AN。

以下N行每行包含M个整数, P11 … PNM。

1 <= N, M <= 1000 1 <= Ai <= M 1 <= Pij <= 100

输出
一个整数代表答案。

样例输入
3 2
1 1 1
1 2
1 1
10 9
样例输出
8

思路:假设当前在第 i i i天,若没有额外 k 2 k^2 k2的限制,我们只需要将前 i i i天用剩下的物资中取价格最小的前 a i a_i ai个即可。

如何消除 k 2 k^2 k2的影响呢?对于第 i i i天的物资价格数组 P P P,我们将 P P P从小到大排好序,然后让 P 1 加 上 1 , P 2 加 上 2 2 − 1 2 , P 3 加 上 3 2 − 2 2 , . . . . . . . , P m 加 上 m 2 − ( m − 1 ) 2 P_1加上1,P_2加上2^2-1^2,P_3加上3^2-2^2,.......,P_m加上m^2-(m-1)^2 P11P22212,P33222.......Pmm2(m1)2

这样加完之后,数组 P P P仍然是递增的,这时我们就把 k 2 k^2 k2的影响消除了,我们在优先选价格低的物资同时,也把 k 2 k^2 k2额外价格加入到了物资原来的价格里。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
priority_queue<int,vector<int>,greater<int> >q;
int p[1001];
int a[1001];
int main()
{
    int n,m;
    cin>>n>>m;
    ll ans=0;
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)scanf("%d",&p[j]);
        sort(p+1,p+m+1);
        for(int j=1;j<=m;j++)p[j]+=2*j-1;
        for(int j=1;j<=m;j++)q.push(p[j]);
        for(int j=1;j<=a[i];j++)ans+=q.top(),q.pop();
    }
    cout<<ans<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值