BZOJ2064状态压缩动态规划

n1和n2都小于等于10,考虑状态压缩动态规划

预处理:

d[ i ][ j ]表示开始状态的子集i,变成结束状态的子集j所需要的步数。(这里需要i的面积和与j的面积和相等,所需要的步数是暴力合并i和暴力拆分j的步数)

DP:

F[ i ][ j ]表示当前剩余状态开始状态的i,和结束状态的j。

枚举i的子集p , j ^ (1 << (n2-1))的子集q // q是全集j的补集的子集

        主动递推:

F[ i ^ p ][ j | q ] = min{ F[ i ][ j ] + d[ p ][ q ] };

注意:

1、动态规划的无后效性,即i从大到小枚举,j从小到大枚举。

2、注意枚举子集的方法

3、要判断i + j的面积是否为全集的面积,否则会TLE


#include 
#include 
#include 
#define N 2049

using namespace std;

int x[N],y[N],n1,n2;
int d[N][N],F[N][N],S,T;

int lowbit(int x) { return (x & (-x)); }

int c(int x) { 
	int t = 0; 
	while (x) {	t++; x -= lowbit(x); } 
	return t; 
}

int sumx(int i) {
	int t = 0 , tmp = 0;
	while (i) {
		t = lowbit(i);
		tmp += x[t];
		i -= t;
	}
	return tmp;
}

int sumy(int i) {
	int t = 0 , tmp = 0;
	while (i) {
		 t = lowbit(i);
		 tmp += y[t];
		 i -= t;
	}
	return tmp;
}

void Pre() {
	
	for (int i=1;i<=(1<=0;i--)
		for (int j=0;j<=(1<


你可能感兴趣的:(BZOJ2064状态压缩动态规划)