2020.01.18【NOIP提高组】模拟B 组——总结——选择困难症

Description

又到吃饭时间,Polo面对饭堂里琳(fei)琅(chang)满(keng)目(die)的各种食品,又陷入了痛苦的抉择中:该是吃手(jiao)打肉饼好呢,还是吃豆(cai)角(chong)肉片好呢?嗯……又不是天秤座怎么会酱紫呢?
具体来说,一顿饭由M个不同的部分组成(荤菜,素菜,汤,甜品,饮料等等),Polo要在每个部分中选一种作为今天的午饭。俗话说的好,永远没有免费的午餐,每种选择都需要有一定的花费。长者常常教导我们,便宜没好货,最便宜的选择估计比较坑爹,可囊中羞涩的Polo还要把钱省下来给某人买生日礼物,这该怎么办呢?
于是一个折中方案出来了:第K便宜的组合要花多少钱?这就要靠你了。

Input

第一行两个数M,K,含义如上所述。
接下来M行,先是一个整数Ai,表示第i个部分有多少种选择。接下来用空格分开的Ai个整数表示每种选择的价格。

Output

一行一个整数表示答案。
【样例解释】
最便宜的选择是第一部分选择1块钱的,第二部分选择2块的。但由于第二部分里2块钱有两种不同的选择,所以第二便宜的总花费仍然是3块。

Sample Input

2 2
2 1 3
2 2 2

Sample Output

3

Data Constraint

在这里插入图片描述

赛时

显然a[i]很大,但是m也小的可怜。想过dp,但是最后打了个二分+dfs+剪枝,当场ac

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
int m,k;
int c[17][500007],a[17];
ll l,r,mid,g,ans;
void dfs(int x,ll sum){
    if(x==m+1){
		g++;
        return;
    }
    if(g>=k) return;
    for(int i=1;i<=a[x];i++){
        if(c[x][i]>sum) return;
        dfs(x+1,sum-c[x][i]);
    }
}
int main(){
    scanf("%d%d",&m,&k);
    for(int i=1;i<=m;i++){
        scanf("%d",&a[i]);
        for(int j=1;j<=a[i];j++) 
			scanf("%d",&c[i][j]);
        sort(c[i]+1,c[i]+a[i]+1);
        l+=c[i][1],r+=c[i][a[i]];
    }
    while(l<=r){
        g=0;
        mid=(l+r)/2;
        dfs(1,mid);
        if(g>=k) r=mid-1,ans=mid;
        else l=mid+1;
    }
    printf("%lld",ans);
}
发布了16 篇原创文章 · 获赞 2 · 访问量 1524

猜你喜欢

转载自blog.csdn.net/jay_zai/article/details/104029983