分裂 状压DP

分裂 状压DP


题目描述:
和久必分,分久必和。。。
中国历史上上分分和和次数非常多。。通读中国历史的\(WJMZBMR\)表示毫无压力。同时经常搞OI的他把这个变成了一个数学模型。

假设中国的国土总和是不变的。 每个国家都可以用他的国土面积代替, 又两种可能,一种是两个国家合并为\(1\)个,那么新国家的面积为两者之和。 一种是一个国家分裂为\(2\)个,那么\(2\)个新国家的面积之和为原国家的面积。

\(WJMZBMR\)现在知道了很遥远的过去中国的状态,又知道了中国现在的状态,想知道至少要几次操作(分裂和合并各算一次操作),能让中国从当时状态到达现在的状态。


此处输入图片的描述

此处输入图片的描述

code:

  //
#include<bits/stdc++.h>
using namespace std;
#define maxnn 6666
int n,m;
int sum1[maxnn];
#define lowbit(i) i&(-i)
int sum2[maxnn];
int dp[maxnn][maxnn];
int all1,all2;
int main()
{
	cin>>n;
	all1=(1<<n)-1;
	for(int i=1;i<=n;i++) scanf("%d",&sum1[1<<i-1]);
	cin>>m;
	all2=(1<<m)-1;
	for(int i=1;i<=m;i++) scanf("%d",&sum2[1<<i-1]);
	for(int i=0;i<=all1;i++) sum1[i]=sum1[i^lowbit(i)]+sum1[lowbit(i)];	
	for(int i=0;i<=all2;i++) sum2[i]=sum2[i^lowbit(i)]+sum2[lowbit(i)];	
	for(int  i=0;i<=all1;i++)
	{
		for(int j=0;j<=all2;j++) 
		{
			for(int p=1;p<=n;p++)
			if(i&(1<<p-1))
			dp[i][j]=max(dp[i][j],dp[i^(1<<p-1)][j]);
			for(int p=1;p<=m;p++)
			if(j&(1<<p-1))
			dp[i][j]=max(dp[i][j],dp[i][j^(1<<p-1)]);
			if(sum1[i]==sum2[j]&&(i!=0&&j!=0)) dp[i][j]++;
		}
	}
	cout<<n+m-2*dp[all1][all2];
}
posted @ 2019-08-30 09:11  ALEZ  阅读(152)  评论(0编辑  收藏  举报