C++题目打卡2.18

从今天开始我们又将讲4天题目。

题目列表

        1.分配T4

                2.组合T5


#分配T4

C++题目打卡2.18_第1张图片

这里很明显是(200 + 110) - 330的差值最小。

我们先想到了一个想法就是输入时哪个堆大,加那个。

#include 
using namespace std;
int main(){
    int n, ans1 = 0, ans2 = 0;
    cin >> n;
    for(int i = 0, a; i < n; i++)
        cin >> a, (ans1 >= ans2 ? ans2 += a : ans1 += a);
    cout << max(ans1, ans2) << ' ' << min(ans1, ans2);
    return 0;
}

就30分。

我们再来看一下正解:

#include 
using namespace std;
int main(){
    int n;
    cin >> n;
    int a[n];
    for(int i = 0; i < n ;i++) cin >> a[i];
    int m = 1 << n; // 2ⁿ个位串
    int dis = 1e4 + 1, ans1 = 1e4 + 1, ans2 = 1e4 + 1;
    for(int plan = 0; plan < m; plan++){
    	int sum1 = 0, sum2 = 0;
    	for(int i = 0; i < n; i++)
    		if(plan & (1 << i)) sum1 += a[i]; // 看plan的第i为是否是1, 如果是加到第一个数组
    		else sum2 += a[i]; // 看plan的第i为是否是0, 如果是加到第一个数组
    	if(abs(sum1 - sum2) < dis){ // 更新成差值最小的
    		ans1 = sum1;
    		ans2 = sum2;
    		dis = abs(sum1 - sum2);
    	}
    }
    cout << max(ans1, ans2) << ' ' << min(ans1, ans2);
    return 0;
}

我们来看一下你不加第一的堆,肯定就要加第二个,那n个,就有2ⁿ 个对吧(长度为n的位串个数)。

C++题目打卡2.18_第2张图片

画的可能不是那么好,但能看懂就行。

我们来看一下3个的位串个数是:

1. 1 1 1                5. 0 1 1

2. 1 1 0                6. 0 1 0

3. 1 0 1                7. 0 0 1

4. 1 0 0                8. 0 0 0

懂了吗


 #组合T5

C++题目打卡2.18_第3张图片

 

样例看明白了吧。

#include 
using namespace std;
int a[10][2], b[10][2], ans = 0, nn, k;
void dfs(int n){
    if(n == 0){
        for(int i = 0; i < nn; i++) a[i][1] = 0;
        for(int i = 0; i < nn; i++) b[i][1] = 0;
        ans++;
        return ;
    }
    for(int i = 0; i < nn; i++)
        for(int j = 0; j < nn; j++)
            if(a[i][1] != 1 && b[j][1] != 1){
                if(a[i][0] >= b[j][1]){
                    a[i][1] = 1, b[i][1] = 1;
                    dfs(--n);
                }else if(k != 0)
                    k--, dfs(--n), a[i][1] = 1, b[i][1] = 1;
            }
}
int main(){
    cin >> nn >> k;
    for(int i = 0; i < nn; i++) cin >> a[i][0], a[i][1] = 0;
    for(int i = 0; i < nn; i++) cin >> b[i][0], b[i][1] = 0;
    dfs(nn);
    cout << ans;
    return 0;
}

看一下这样只能的50分。

我们再来看一下满分的代码很简单。

#include
#define _for(i, a, b) for(int i = (a); i < (int)(b); i++)
using namespace std;

int main(){
    int n, k; cin>>n>>k;
    vector A(n), B(n), P(n);        //A记录男生身高,B记录女生身高,P用于枚举女生次序的排列,A[i]和B[P[i]]组合 
    _for(i, 0, n) cin>>A[i];
    _for(i, 0, n) cin>>B[i];
    _for(i, 0, n) P[i] = i;                //初始排列,012...n-1, 即A[0]和B[0]组合,A[1]和B[1]组合,…… 
    int ans = 0;
    do{
        int cnt = 0;                    //cnt记录当前方案有多少对组合是男生比女生更矮 
        _for(i, 0, n)
            if(A[i] < B[P[i]]) cnt++;    //如果第i位男生A[i] 比 当前方案中第i位女生 B[P[i]] 矮,则cnt增加 
        ans += (cnt <= k);                //如果 男生比女生更矮 的数量超过k,则该方案不合理,反之该方案合理,最终答案+1 
    } while(next_permutation(P.begin(), P.end()));    //枚举下一个女生的排列 
    cout<

最主要是next_permutation该怎么用。

有人可能不知道这个东西,我们先来试验一下。

#include 
using namespace std;
int main(){
    string s = "1234";
    do{
        cout << s <<'\n';
    }while(next_permutation(s.begin(), s.end()));
    return 0;
}

会输出:

C++题目打卡2.18_第4张图片

这样一串东西,这就是1234的所有排列,当然string 也可以换成vector | int。

next_permutation还有一个好处就是,如果有重复的东西不算重复的排列。

C++题目打卡2.18_第5张图片

 

你可能感兴趣的:(c++,开发语言)