[题目链接](https://vjudge.net/problem/Gym-100803A)
题意:
直接看第一个样例,6是第二行的0/1的个数,3是第三行的数字的个数。
第三行可解释为以下两种情况:
- 1 000 11
- 0 111 00
第二行的串,求用最少的交换次数(只能相邻交换),变成第三行的某一种串。
做法:
先预处理两种情况,考虑到样例2中的4不能表示为4个连续的1,所以统计1的个数,跳过不符合条件的情况。
然后,对每种可能的情况,从左至右挨个比较,若不相同,原串当前数字,与原串当前位置后的,第一个与目标串当前数字相等的数字交换,统计相邻交换的次数(j - i)。
反省:
- 1 3 2说明并不是2^n,而是2种情况
- 相邻交换
- 直接统计交换次数–>从串后往前看,前一次的交换“不影响”当次的交换次数
#include <stdio.h>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
int n, m;
int // 串a中1的个数
f(int a[20]) {
int i, total = 0;
for( i = 0; i < n; i++ ) {
if( a[i] == 1 ) {
total++;
}
}
return total;
}
int
main() {
//freopen("in.txt", "r", stdin);
int i, j, t, ta, tb, tans;
int s[20], r[20], a[20], b[20], p[20];
while( scanf("%d %d", &n, &m) != EOF ) {
for( i = 0; i < n; i++ ) {
scanf("%d", &s[i]);
r[i] = s[i];
}
for( i = 0; i < m; i++ ) {
scanf("%d", &p[i]);
}
// 预处理
t = 0;
for( i = 0; i < m; i++ ) {
if( i % 2 == 0 ) {
for( j = 0; j < p[i]; j++ ) {
a[t++] = 1;
}
}
else {
for( j = 0; j < p[i]; j++ ) {
a[t++] = 0;
}
}
}
t = 0;
for( i = 0; i < m; i++ ) {
if( i % 2 != 0 ) {
for( j = 0; j < p[i]; j++ ) {
b[t++] = 1;
}
}
else {
for( j = 0; j < p[i]; j++ ) {
b[t++] = 0;
}
}
}
// for( i = 0; i < n; i++ ) {
// printf("%d %d %d\n", r[i], a[i], b[i]);
// }
// printf("%d %d %d\n", f(a), f(b), f(s));
ta = tb = 0;
if( f(a) != f(s) ) {
ta = INF;
}
else {
for( i = 0; i < n; i++ ) {
if( s[i] != a[i] ) {
for( j = i + 1; j < n; j++ ) {
if( s[j] == a[i] ) {
swap(s[i], s[j]);
ta += (j - i); // j - i
break;
}
}
}
}
}
// for( i = 0; i < n; i++ ) {
// printf("%d %d %d\n", s[i], a[i], b[i]);
// }
// printf("\n");
if( f(b) != f(r) ) {
tb = INF;
}
else {
for( i = 0; i < n; i++ ) {
if( r[i] != b[i] ) {
for( j = i + 1; j < n; j++ ) {
if( r[j] == b[i] ) {
swap(r[i], r[j]);
tb += (j - i); // j - i
break;
}
}
}
}
}
// for( i = 0; i < n; i++ ) {
// printf("%d %d %d\n", r[i], a[i], b[i]);
// }
// printf("%d %d\n", ta, tb);
tans = min(ta, tb);
printf("%d\n", tans);
}
return 0;
}