[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);
}
 

 

posted @ 2017-08-14 16:38  人间失格—太宰治  阅读(498)  评论(0编辑  收藏  举报