4397 卡牌(贪心)

1. 问题描述:

有 n 张卡牌,编号 1∼n,每张卡牌的正面和背面都各有一个数字,第 i 张卡牌的正面数字为 ai,背面数字为 bi,初始时,所有卡牌都正面朝上,显示正面的数字,现在你可以将其中一些卡牌翻面,使其显示背面的数字,要求:
至少有 k 张卡牌保持正面朝上;
所有卡牌显示的数字之和尽可能小;
输出所有卡牌显示的数字之和的最小可能值;

输入格式

第一行包含两个整数 n,k,第二行包含 n 个整数 a1,a2,…,an,第三行包含 n 个整数 b1,b2,…,bn;

输出格式

一个整数,表示所有卡牌显示的数字之和的最小可能值。

数据范围

前 6 个测试点满足 1 ≤ n ≤ 10;
所有测试点满足 1 ≤ n ≤ 2 × 10 ^ 5,0 ≤ k ≤ n,1 ≤ ai,bi ≤ 10 ^ 4。

输入样例1:

3 1
5 4 6
3 1 5

输出样例1:

10

输入样例2:

5 3
3 4 7 10 3
4 5 5 12 5

输出样例2:

25
来源:https://www.acwing.com/problem/content/description/4400/

2. 思路分析:

分析题目可以知道正面显示数字的总和 s 是一定的,一开始所有卡牌都正面向上,我们最多可以翻转 n - k 张卡牌,使得最终卡牌显示的数字之和最小,可以发现每当我们翻转一张卡牌,那么 s 减少的是卡牌正面和反面数字的差值,所以我们肯定是先翻转那些差值贡献值大于 0 而且当前差值最大的卡牌,基于这个想法我们使用 vector 或者列表 q 记录下 每一个 a[i] - b[i] 的差值,最后对 q 从大到小排序,在 q 中最多找到 n - k 张贡献值大于 0 的卡牌,用 s 减去这些大于 0 的差值即可。

3. 代码如下:

python:

class Solution:
    def process(self):
        n, k = map(int, input().split())
        # a 表示正面显示的数字, b 表示背面显示的数字, 正面显示数字的总和是一定的所以需要选择a[i]-b[i]差值最大的数字
        a = list(map(int, input().split()))
        b = list(map(int, input().split()))
        # s 记录a中所有元素的总和
        s = 0
        q = list()
        for i in range(n):
            x = a[i]
            s += x
            # q记录a和b的差值
            q.append(a[i] - b[i])
        # 对 q 从大到小排序
        q.sort(reverse=True)
        # 我们至多选择n - k个差值最大的这些卡牌, 并且需要选择那些贡献值大于0的卡牌, 如果贡献值小于等于0还不如不翻牌
        for i in range(n - k):
            if q[i] > 0:
                s -= q[i]
            else:break
        print(s)


if __name__ == '__main__':
    Solution().process()

go:

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"sort"
)

func run(r io.Reader, w io.Writer) {
    // 使用bufio优化输入输出数据的读取和输出效率
	in := bufio.NewReader(r)
	out := bufio.NewWriter(w)
    // 将缓存数据输出到标准输出中
	defer out.Flush()
	var (
		n, k int
	)
	fmt.Fscan(in, &n, &k)
	a := make([]int, n+10)
	b := make([]int, n+10)
	s := 0
	q := make([]int, n+10)
	for i := 0; i < n; i++ {
		fmt.Fscan(in, &a[i])
		s += a[i]
	}
	for i := 0; i < n; i++ {
		fmt.Fscan(in, &b[i])
		q = append(q, a[i]-b[i])
	}
	// 对b从大到小排序
	sort.Sort(sort.Reverse(sort.IntSlice(q)))
	for i := 0; i < n-k; i++ {
		if q[i] > 0 {
			s -= q[i]
		} else {
			break
		}
	}
	fmt.Fprintln(out, s)
}

func main() {
	run(os.Stdin, os.Stdout)
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值