中国历史Bzoj 2064 分化 题解

2064: 分裂

Time Limit: 10 Sec  Memory
Limit: 64 MB
Submit: 570  Solved: 350
[Submit][Status][Discuss]

Description

背景: 和久必分,分久必和。。。 标题描述:
中华夏族民共和国野史上上分分和和次数万分多。。通读中华夏族民共和国历史的WJMZBMOdyssey表示并非压力。
同时经常搞OI的他把这一个变成了多少个数学模型。 假若中中原人民共和国的版图总和是不变的。
各个国家都足以用她的国土面积代替,
又二种恐怕,一种是二国统一为贰个,那么新江山的面积为双方之和。
一种是2国解体为3个,那么3个新江山的面积之和为原国家的面积。
WJMZBM中华V今后清楚了很深远的过去中华人民共和国的景况,又亮堂了华夏到以往的意况,想理解至少要三回操作(分化和合并各算1次操作),能让中国从霎时处境到达现在的状态。

Input

先是行1个数n1,表示马上的块数,接下去n贰个数分别表示各块的面积。
第①行三个数n2,表示以往的块,接下去n三个数分别表示各块的面积。

Output

一行叁个数表示小小的次数。

Sample Input

1 6
3 1 2 3

Sample Output

2
数据范围:
对于100%的数据,n1,n2<=10,每个数<=50
对于30%的数据,n1,n2<=6,

HINT

 

Source

和谐社会模拟赛

  那道题真心和谐啊,连题解都搜不到,黄学长都说“只可意会,不可言传”。逗作者呢?!

  于是乎本着良心作者说了算言传一下。

  我们得以先把那些国家想成橡皮泥,我们的目标就是把一堆橡皮泥变成另一堆橡皮泥。考虑最多的步数,正是我们先把具有橡皮泥揉到一块儿,然后再挨个往外掰,那么步数就是n1+n2-2。

  可是,我们能够小心到,假诺大家得以再把当下的两堆橡皮泥分成4堆,两两对应,那么,大家就不曾要求把两堆在和在联合在分手了。换句话说,大家把它分解成了八个子难点,而那样做的口径就是两两对应的堆大小也等于。然后七个小堆大概被大家随后往下分,然后又省了两步,然后……

  所以,要是大家那样做最多可以分为k对,那么答案正是n+m-2*k。

  那么难题来了,我们究竟怎么去求呢?

  数据范围如此小,大家能够设想状压一发。为了方便,大家把两堆合在一起状压,状态正是看那个橡皮泥选没选,然后挨个去找最佳的更换,最终看一下脚下景观是还是不是也是能够整合两两配对的两堆的,假若是,那么f[i]+1,因为刨去i表示的橡皮泥剩下的也必然是两两配对的。

中国历史 1中国历史 2

 1 #include <iostream>
 2 #include <cstdlib>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <queue>
 6 #include <algorithm>
 7 #include <cmath>
 8 #include <map>
 9 #include <vector>
10 #define N (1<<21)
11 using namespace std;
12 int f[N],sum[N];
13 int n1,n2,n;
14 int a[100],b[100];
15 int main()
16 {
17     scanf("%d",&n1);
18     for(int i=1;i<=n1;i++)
19     {
20         scanf("%d",&a[i]);
21         sum[(1<<(i-1))]=a[i];
22     }
23     scanf("%d",&n2);    
24     for(int i=1;i<=n2;i++)
25     {
26         scanf("%d",&b[i]);
27         sum[(1<<(i-1+n1))]=-b[i];
28     }
29     n=n1+n2;
30     for(int i=1;i<(1<<n);i++)
31     {
32         sum[i]=sum[i&(-i)]+sum[i-(i&(-i))];
33         for(int j=1;j<=n;j++)
34         {
35             if(i&(1<<(j-1)))
36             {
37                 f[i]=max(f[i],f[i-(1<<(j-1))]);
38             }
39         }
40         if(!sum[i])f[i]++;
41     }
42     printf("%d\n",n-2*f[(1<<n)-1]);
43     return 0;
44 }

View Code

发表评论

电子邮件地址不会被公开。 必填项已用*标注