[질문 솔루션] LuoGu3943 : 별이 빛나는 하늘

k <= 8 k <= 8
이기 때문에 원래 타이틀 포털케이<=8 그래서 생각해

주된 아이디어는
빛을 1로 어둡게 만들고 빛을 0 으로 만드는 것입니다. 예를
들어, 줄의 빛의 경우
: 01001100 a : 01001100:0 1 0 0 1 1 0 0
그러면 대응하는 차이 배열은
b : 011010100 b : 011010100입니다.:0 1 1 0 1 0 1 0 0
可以发现= B 1 2 xorb XOR 인공 지능. . . xorbi a_i = b_1xorb_2xor ... xorb_i나는=(1)x o r bx 또는 r . . . x o r b나는
그런 다음 간격 [l, r] [l, r][ l ,r ] 은 반전 연산을 수행하고 차이 배열의 성능은
bl = blxor 1, br + 1 = br + 1 xor 1 b_l = b_lxor1, b_ {r + 1} = b_ {r + 1} xor1입니다.리터=리터x o r 1 ,R + 1=R + 1x o r 1

문제는 bb 로 변환 될 수 있습니다.b 배열이 모두 0이 됨
findbbb 배열 1의 수는 짝수 여야하며 최대2k 2k2 K 번째
둘 다를 비용 제거하기 위해, 1 매 2를 제거 생각할 다음 상태가 미리 결정된 눌렀을

10000001 10000001 을 넣으려면1 0 0 0 0 0 0 1 은 모두 0이되지만 길이를 3으로 만 뒤집을
수 있습니다. 4는 먼저00010001 000100010 0 0 1 0 0 0 1[1, 3] [1, 3]을 의미합니다.[ 1 ,3 ]
다시뒤집기00000000 000000000 0 0 0 0 0 0 0[4, 7] [4, 7]을 의미합니다.[ 4 ,7 ]
둘 사이의 차이가xx임을 나타 내기위해 뒤집기x /111. 0으로 변경 하려면 x = b 1 + b 2 + ... + Byx = b_1 + b_2 + ... + b_y를 선택합니다.엑스=(1)++. . .+
여러 플립 조합 가능

또는 00110000 00110000 입력0 0 1 1 0 0 0 0은 모두 0이되고,하지만 단지 4, 3 길이를 플립 할
수있는 제00,010,010 00,010,010을0 0 0 1 0 0 1 0[3, 6] [3, 6]을 의미합니다.[ 3 ,6 ]
다시뒤집기00000000 000000000 0 0 0 0 0 0 0[4, 6] [4, 6]을 의미합니다.[ 4 ,6 ] 반전
은 반전 간격 길이 사이의 뺄셈도 가능함을 보여줍니다.

따라서 특정 길이에 대해 bb를 전달합니다.b 배열을 더하고, 더하고, 빼고, 빼서 자신의 길이를 얻을 수 있습니다. 합리적인 상황에서 최소 플립 수를 찾아서 완전한 배낭을 통해 얻습니다.

암호:

#include <bits/stdc++.h>
#define maxn 40010
#define maxm 100010
using namespace std;
int a[maxn], dp[maxm], cost[maxn], b[maxn], pos[maxn], power[25], tot, n, m, k;

inline int read(){
    
    
	int s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
	return s * w;
}

int main(){
    
    
	n = read(), k = read(), m = read();
	for (int i = 1; i <= k; ++i){
    
    
		int x = read();
		a[x] ^= 1, a[x + 1] ^= 1;
	}
	for (int i = 1; i <= n; ++i) cost[i] = 1e9;
	for (int i = 1; i <= m; ++i) b[i] = read();
	for (int i = 1; i <= m; ++i)
		for (int j = b[i]; j <= n; ++j) cost[j] = min(cost[j], cost[j - b[i]] + 1);
	for (int i = 1; i <= m; ++i)
		for (int j = n - b[i]; j >= 0; --j) cost[j] = min(cost[j], cost[j + b[i]] + 1);
	for (int i = 1; i <= n + 1; ++i)
		if (a[i]) pos[++tot] = i;
	power[0] = 1;
	for (int i = 1; i <= 20; ++i) power[i] = power[i - 1] << 1;
	for (int i = 1; i < power[tot]; ++i) dp[i] = 1e9;
	for (int i = 0; i < power[tot]; ++i)
		for (int j = 1; j <= tot; ++j)
			if (!(i & power[j - 1]))
				for (int k = j + 1; k <= tot; ++k)
					if (!(i & power[k - 1]))
						dp[i | power[j - 1] | power[k - 1]] = min(dp[i | power[j - 1] | power[k - 1]], dp[i] + cost[pos[k] - pos[j]]);
	printf("%d\n", dp[power[tot] - 1]);
	return 0;
}

추천

출처blog.csdn.net/ModestCoder_/article/details/108491966