码迷,mamicode.com
首页 > 其他好文 > 详细

ZOJ 4067 Books (2018icpc青岛J) (贪心)

时间:2019-09-20 23:37:33      阅读:153      评论:0      收藏:0      [点我收藏+]

标签:print   double   算法   for   main   tis   min   size   can   

题意

给你一个长度为n的数组,代表每一个物品的价格。你有一个初始钱数\(x\),采用以下方法贪心:
\(1\)\(n\)扫一遍,如果\(x\)不比\(a[i]\)小,就买下它,买不起就跳过。
给你最终买的物品数量m,求\(x\)的最大值。

思路

我队的贪心菜的一笔,果然我也有很大的责任。。
首先如果最后全部买完,那么刚开始的钱一定是无穷多的。
我们先假设数组里没有0,那么通过题意中的贪心方法,最后买的一定是前m个
证明:
\(m=0\)的时候,显然成立。
假设当\(m=i\)的时候成立,即已经连续买了前\(i\)个。
买第\(i+1\)个的时候,如果不买\(a[i+1]\),而买了\(a[j]\)\(j>i+1\):
①当\(a[i+1]\leq a[j]\)时,由于题意中的贪心,如果买了\(a[j]\),对于\(j>i+1\),且\(a[j]\geq a[i+1]\)时,\(a[i+1]\)是必买的,所以不成立
②当\(a[i+1]>a[j]\)时,由于两个位置对m的贡献都为1,为使答案最大,还是要选最大的\(a[i+1]\)
综上所述,此时要买\(a[i+1]\)
再综上所述,最后买的一定是前m个
所以,没有0的时候,我们直接买前m个即可
当数组里是有0时,因为永远可以买0,所以要从m里减去0的个数,然后对剩下的数做上述算法
当然如果0的个数本身就超过\(m\),就是\(impossible\)的。

代码

注释提供了一些假算法的插点

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
#include<functional>
    
#define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1
#define lowbit(x) ((x)&(-x)) 

using namespace std;

typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL;

const db eps = 1e-6;
const int mod = 1e9+7;
const int maxn = 3e6+100;
const int maxm = 2e6+100;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0);

int n,m;
ll a[maxn];
int cnt;
ll sum[maxn];
multiset<ll>s;
int main() {
    int t;
    scanf("%d", &t);
    while(t--){
        cnt=0;
        scanf("%d %d", &n, &m);
        for(int i = 1; i <= n; i++){
            scanf("%lld", &a[i]);
            if(!a[i])cnt++;
        }
        if(n==m){
            printf("Richman\n");continue;
        }
        if(cnt>m){
            printf("Impossible\n");continue;
        }
        ll ans=0;
        m-=cnt;
        int p = 0;
        int num=0;
        for(int i = 1; i <= n&&num<m; i++){
            if(a[i]){ans+=a[i];p=max(p,i);num++;}
        }
        //printf("  %d\n",p);
        ll mi = 0x7f7f7f7f7f7f7f7f;
        for(int i = p+1; i <= n; i++){
            if(a[i])mi=min(mi,a[i]);
        }
        if(mi==0x7f7f7f7f7f7f7f7f){
            printf("Richman\n");continue;
        }
        printf("%lld\n",mi-1+ans);
    }
    return 0;
}
/*
2
7 6
4 1 0 3 0 0 1
6 5
4 5 0 3 0 0

 */

ZOJ 4067 Books (2018icpc青岛J) (贪心)

标签:print   double   算法   for   main   tis   min   size   can   

原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/11560174.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!