从今天开始我们又将讲4天题目。
题目列表
1.分配T4
2.组合T5
#分配T4
这里很明显是(200 + 110) - 330的差值最小。
我们先想到了一个想法就是输入时哪个堆大,加那个。
#include <bits/stdc++.h>
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 <bits/stdc++.h>
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的位串个数)。
画的可能不是那么好,但能看懂就行。
我们来看一下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
样例看明白了吧。
#include <bits/stdc++.h>
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<bits/stdc++.h>
#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<int> 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<<ans;
return 0;
}
最主要是next_permutation该怎么用。
有人可能不知道这个东西,我们先来试验一下。
#include <bits/stdc++.h>
using namespace std;
int main(){
string s = "1234";
do{
cout << s <<'\n';
}while(next_permutation(s.begin(), s.end()));
return 0;
}
会输出:
这样一串东西,这就是1234的所有排列,当然string 也可以换成vector | int。
next_permutation还有一个好处就是,如果有重复的东西不算重复的排列。