zoukankan      html  css  js  c++  java
  • [JOJZ]3855.选择困难症

    【问题描述】
    又到吃饭时间,Polo 面对饭堂里琳(fei)琅(chang)满(keng)目(die)的各种食品,
    又陷入了痛苦的抉择中:该是吃手(jiao)打肉饼好呢,还是吃豆(cai)角(chong)肉片
    好呢?嗯……又不是天秤座怎么会酱紫呢?
    具体来说,一顿饭由 M 个不同的部分组成(荤菜,素菜,汤,甜品,饮料等
    等),Polo 要在每个部分中选一种作为今天的午饭。俗话说的好,永远没有免费
    的午餐,每种选择都需要有一定的花费。长者常常教导我们,便宜没好货,最便
    宜的选择估计比较坑爹,可囊中羞涩的 Polo 还要把钱省下来给某人买生日礼物,
    这该怎么办呢?
    于是一个折中方案出来了:第 K 便宜的组合要花多少钱?这就要靠你了。
    【输入】
    第一行两个数 M,K,含义如上所述。
    接下来 M 行,先是一个整数 Ai,表示第 i 个部分有多少种选择。接下来用
    空格分开的 Ai 个整数表示每种选择的价格。
    【输出】
    一行一个整数表示答案。
    【输入输出样例】
    perdant.in perdant.out
    2 2
    2 1 3
    2 2 2
    3
    【样例解释】
    最便宜的选择是第一部分选择 1 块钱的,第二部分选择 2 块的。但由于第二
    部分里 2 块钱有两种不同的选择,所以第二便宜的总花费仍然是 3 块。
    【数据规模和约定】
    10%的数据
    M i
    Ai
    1
    <=1000,M<=2。
    30%的数据有 M<=2。
    50%的数据有 K<=1000。
    100%的数据有 Ai>0,
    M i
    Ai
    1
    <=500000,1<=M<=10,1<=K<=100000,1<=
    价格<=10^8。

    题解:

    这个题目,考试的时候想到k短路,但k短路只会A星的做法,所以就愉快的爆空间了。然后开了同学的做法,首先可以二分一个答案,但是怎么check?可以dfs,但dfs写的太丑能只有50分,于是要加剪枝,如果当前的总花费已经大于了二分的答案就不要再搜了(十分显然),如果当前的合法(总数比二分的答案小)方案数已经大于了k,就可以返回了。

    代码:

    #include<iostream>
    #include<stdio.h>
    #include<stdlib.h>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #define ll long long
    using namespace std;
    int m,k;
    int cost[11][50011],lenn[15],flag=0;
    ll l=0,r=0,sum=0;
     
    void check(int dep,ll rest){
        if(dep==m+1){
            sum++;
            return;
        }
        if(sum>=k) return;
        for(int i=1;i<=lenn[dep];i++){
            if(cost[dep][i]>rest) return;
            check(dep+1,rest-cost[dep][i]);
        }
    }
    int main(){
        scanf("%d%d",&m,&k);
        for(int i=1;i<=m;i++){
            scanf("%d",&lenn[i]);
            for(int j=1;j<=lenn[i];j++) scanf("%d",&cost[i][j]);
            sort(cost[i]+1,cost[i]+lenn[i]+1);
            l+=cost[i][1],r+=cost[i][lenn[i]];
        }
        ll mid,ans;
        while(l<=r){
            mid=(l+r)/2;
            sum=0;
            check(1,mid);
            if(sum>=k) r=mid-1,ans=mid;
            else l=mid+1;
        }
        printf("%lld",ans);
    }
     
  • 相关阅读:
    周赛F题 POJ 1458(最长公共子序列)
    HDU 4720 Naive and Silly Muggles 2013年四川省赛题
    HDU 4716 A Computer Graphics Problem 2013年四川省赛题
    SCU 4440 Rectangle 2015年四川省赛题
    SCU 4436 Easy Math 2015年四川省赛题
    大数模板——六种实现了加减乘除和求余
    HDU 1002 A + B Problem II
    CodeForces 689C  Mike and Chocolate Thieves
    CodeForces 689A -Mike and Cellphone
    CodeForces 595B
  • 原文地址:https://www.cnblogs.com/renjianshige/p/7358602.html
Copyright © 2011-2022 走看看