有 n 张卡牌,编号 1∼n。
每张卡牌的正面和背面都各有一个数字。
第 ii 张卡牌的正面数字为 ai,背面数字为 bi。
初始时,所有卡牌都正面朝上,显示正面的数字。
现在,你可以将其中一些卡牌翻面,使其显示背面的数字,要求:
- 至少有 k 张卡牌保持正面朝上。
- 所有卡牌显示的数字之和尽可能小。
输出所有卡牌显示的数字之和的最小可能值。
输入格式
第一行包含两个整数 n,k。
第二行包含 nn 个整数 a1,a2,…,an。
第三行包含 nn 个整数 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
我给大家讲一下我自己的思路,首先将正面的所有数加在一起,保存在一个变量d中,然后要求最少的总和,也就是说,如果背面的数大于正面的数,那么就不翻,背面比正面的数少的越多,就要翻,那么怎样求呢?我们可以将每一组正面-反面的数存入一个数组中,然后用sort从大到小的排序,将其中大于0的数和 d相减,只能取sort排序后最大的k个数,但是我们每必要翻k个卡牌,只要小于k就行了,那么怎么小于k呢?判断到为负数或者0就停止,最后输出d,这样就会输出最小的一组数了。
我的代码:
#include <bits/stdc++.h>
#include <iostream>
#include<algorithm>
using namespace std;
bool cmp(int i, int j)
{
return i > j;
}
int main()
{
int n,k;
cin>>n>>k;
int a[n],b[n],c[n],d;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<n;i++) cin>>b[i];
for(int i=0;i<n;i++) c[i]=a[i]-b[i];
for(int i=0;i<n;i++) d+=a[i];
sort(c,c+n,cmp);
for(int i=0;i<n-k;i++)
{
if(c[i]>=0)
d-=c[i];
else if(c[i]<0)
break;
}
cout<<d<<endl;
}
在这里我们没有必要采用快速排序法,因为用sort排序时间是允许的,我们已知sort排序是从小到大的排序,我们则需要加一个bool函数,加在sort函数后面,这样就可以将sort函数中的数从大到小排序了。
bool函数:
bool cmp(int i, int j)
{
return i > j;
}
因为是i>j,所以我们就是你从大到小排序了。
刚开始,我和我的爸爸想出来了一个错误的思路,因为我们运用位运算用惯了,所以我们想枚举出所有的方法,将里面的每一组数据,从小到大的排序,第一个数就是最少的一组数,但是n已经达到10的5次方,10的5次方是多少,100,000,也就是说我们最大需要二进制中的100,000多为,哪怕是最大变量类型long long 也不过是一百多位而已,100,000这么多位,铁定是错的,恐怕要算上亿年啊!
好了,今天就到这里了,大家拜拜!