H - Buying Products (SDUT 2018 Autumn Individual Contest - F)

Salim为了满足妻子的要求,必须在限定条件下购买指定数量的商品。面对每个店铺仅能购买两件商品的限制,Salim如何在众多选项中找到最低价格组合?本篇将通过算法解决这一有趣又实际的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

滴答滴答--题目链接 

Salim (a.k.a Slango) and his wife fight all the time. When Salim came home at night, his needy wife Afaf (a.k.a Afoufe) was waiting for him at the door.

"You don't buy any products for this house! You are a lousy husband! Well guess what?? You are not coming home before buying me exactly Kproducts, or you are sleeping on the streets!!". Said his wife.

"I'm going to buy you these products, but when you open that door you are divorced by 3 you needy wife!!". Thought Salim to him self.

Anyway, having no other option, Salim went down the stairs and headed to the nearby mall. the mall has exactly N shops. Salim knows that each of these shops has exactly 3 products (it's sales time and shops are almost empty).

However, Salim knows that buying all the 3 products of some shop will cause the owner of the shop to ask him for a huge amount of money, because he will say that the last piece is very rare. Thus, he made a rule, he will buy at most 2 products from every shop.

Salim is really tired and he just wants to go home and sleep a while in order to wake up in the morning and divorce his needy wife. Also, Salim doesn't really care about the quality of the products, he just wants to buy them with the lowest possible price. Can you help him calculate the minimum amount of money he needs to spend in order to buy his wife exactly K products, while buying at most 2 products from any given shop?

Input

The first line contains an integer T, the number of test cases.

The first line of each test case contains 2 space separated integer Nand K (1 ≤ N ≤ 1000)(1 ≤ K ≤ 2N).

N lines follows. The ith line contains exactly 3 space separated integers denoting the prices of the 3 products at the ith shop. (1 ≤ Pij ≤ 106)

Output

For each test case print a single line, containing a single integer, denoting the minimum price needed to buy exactly K products from the given shops while fulfilling the above given condition.

Example

Input

1
3 4
1 10 300
4 5 6
1 100 1

Output

7
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,k;
        scanf("%d%d",&n,&k);
        int b[2010];
        int ll=0;
        int x1,y1;
        for(int i=1; i<=n; i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            if(x>=y&&x>=z)x1=y,y1=z;
            else if(y>=x&&y>=z)x1=x,y1=z;
            else if(z>=x&&z>=y)x1=x,y1=y;
            b[ll++]=x1;
            b[ll++]=y1;
        }
        int ans=0;
        sort(b,b+ll);
        int o=0;
        for(int i=0; i<ll; i++)
        {
            if(o!=k)
            {
                o++;
                ans+=b[i];
            }
        }
        printf("%d\n",ans);
    }

    return 0;
}

 

<think>嗯,用户想要找山东理工大学C语言实验中的全排列问题的解法或示例代码。让我先看看他们提供的引用内容。引用2和引用4都提到了全排列问题,其中引用2的代码用了递归和标记数组的方法,而引用4的代码则通过交换元素来生成排列。用户可能需要这两种方法的比较或者其中一种的具体实现。 首先,我需要确认全排列问题的具体要求。通常全排列指的是生成一个数列所有可能的排列方式。比如输入是1,2,3,输出所有的排列组合。引用2的代码使用了vis数组来标记哪些元素已经被使用过,通过回溯的方式构建排列。而引用4的代码则采用了交换法,递归地生成每个位置的元素,不需要额外的标记数组,但需要处理元素的交换和恢复。 用户可能希望得到这两种方法的解释,或者其中一种的详细步骤。同时,他们可能需要代码示例以及对应的分析。比如,引用2中的代码结构是怎样的,如何递归生成排列,而引用4的方法是如何通过交换来实现的。需要注意代码的可读性和正确性,是否处理了边界情况,比如n=0或者n=1的情况。 另外,用户提供的引用中有不同的代码风格,比如引用2使用了全局变量,而引用4将数组作为参数传递。可能需要指出不同实现的优缺点,比如全局变量可能带来的问题,或者交换法的空间效率更高等。 接下来,我应该组织回答的结构,先介绍全排列问题的基本概念,然后分别讲解两种解法,给出代码示例,并分析其思路和关键步骤。最后,可以比较两种方法的优缺点,帮助用户理解不同实现方式的适用场景。 还要注意用户提到的SDUT实验题目的具体要求,比如输入输出的格式,是否需要处理多组数据等。引用2中的代码似乎处理单个测试用例,而引用4的代码通过while循环处理多个测试用例,这可能也是用户需要注意的地方。 最后,生成相关问题的时候,应该围绕全排列的不同解法、优化方法、应用场景等展开,帮助用户进一步深入学习。</think>### SDUT C语言实验全排列问题解析 全排列问题要求输出给定数字序列的所有排列方式。山东理工大学的实验题目提供了两种典型解法,分别采用**回溯标记法**和**元素交换法**。 --- #### 方法一:回溯标记法(引用[2]) **核心思路**:使用标记数组`vis[]`记录元素使用状态,递归构建排列结果。 ```c #include<stdio.h> #include<stdlib.h> int a[15], vis[15], b[15]; int n; void next_(int k, int m) { if(k == m + 1) { // 完成一个排列 for(int i=0; i<=m; i++) { printf(i==0?"%d":",%d", b[i]); } printf("\n"); } else { for(int i=0; i<=m; i++) { if(vis[i] == 0) { // 选择未使用的元素 vis[i] = 1; b[k] = a[i]; // 记录当前选择 next_(k+1, m); // 递归下一层 vis[i] = 0; // 回溯 } } } } int main() { scanf("%d", &n); for(int i=0; i<n; i++) { scanf("%d", &a[i]); } next_(0, n-1); return 0; } ``` **关键点**: 1. 时间复杂度为$O(n!)$,空间复杂度$O(n)$ 2. 使用`vis[]`数组避免重复选择元素 3. 输出格式要求用逗号分隔[^2] --- #### 方法二:元素交换法(引用[4]) **核心思路**:通过交换数组元素的位置直接生成排列。 ```c #include <stdio.h> #include <stdlib.h> void p(int a[], int k, int m) { if(k == m) { // 完成一次排列 for(int i=1; i<m; i++) printf("%d,",a[i]); printf("%d\n",a[m]); } else { for(int i=k; i<=m; i++) { // 交换元素位置 int t = a[k]; a[k] = a[i]; a[i] = t; // 递归生成后续排列 p(a, k+1, m); // 恢复原始位置 t = a[k]; a[k] = a[i]; a[i] = t; } } } int main() { int t, n, a[11]; scanf("%d", &t); while(t--) { scanf("%d", &n); for(int i=1; i<=n; i++) scanf("%d", &a[i]); p(a, 1, n); } return 0; } ``` **关键点**: 1. 时间复杂度同样为$O(n!)$,但空间效率更高 2. 通过元素交换避免使用额外标记数组 3. 支持多组测试数据输入[^4] --- #### 方法对比 | 特性 | 回溯标记法 | 元素交换法 | |-----------|-------------------|------------------| | 空间复杂度 | $O(n)$ | $O(1)$ | | 元素顺序 | 保持原始顺序 | 产生位置交换后的顺序 | | 适用场景 | 需要保留原始数组时 | 允许修改原数组时 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值