状压DP 分裂

问题 E: 分裂
时间限制: 1 Sec 内存限制: 128 MB
提交: 53 解决: 24
[提交][状态][讨论版]
题目描述
Description
背景: 和久必分,分久必和。。。 题目描述: 中国历史上上分分和和次数非常多。。通读中国历史的WJMZBMR表示毫无压力。 同时经常搞OI的他把这个变成了一个数学模型。 假设中国的国土总和是不变的。 每个国家都可以用他的国土面积代替, 又两种可能,一种是两个国家合并为1个,那么新国家的面积为两者之和。 一种是一个国家分裂为2个,那么2个新国家的面积之和为原国家的面积。 WJMZBMR现在知道了很遥远的过去中国的状态,又知道了中国现在的状态,想知道至少要几次操作(分裂和合并各算一次操作),能让中国从当时状态到达现在的状态。
Input
第一行一个数n1,表示当时的块数,接下来n1个数分别表示各块的面积。 第二行一个数n2,表示现在的块,接下来n2个数分别表示各块的面积。
Output
一行一个数表示最小次数。
Sample Input
1 6
3 1 2 3
Sample Output
2
数据范围:
对于100%的数据,n1,n2<=10,每个数<=50
对于30%的数据,n1,n2<=6,

网上好多“只可意会不可言传”,但我打算做一次非主流。
口胡开始:
最坏的答案是n+m-2。就是把所有的聚成一堆,再拆成m堆。那么如果把较少的子集合并成一堆后与结束状态的某些子集合并后值一样,那么就没必要再把它合并成一大块了,这样步数就减少了。
很容易想到状压。f[i][j]表示对于初始状态的子集i和结束状态的子集j,二者最多可产生多少堆。分别枚举i,j的子集,先直接转移,找到一种堆数最大的方案,如果i的值==j的值,那就一定可以再合并出一堆。
最后步数=n+m-2*f[totn][totm]
可能是我傻。。。枚举子集时强行加了一个2^n。。。其实只要枚举去掉一个元素的子集就行了,因为这个子集已从其他子集转移过了。所以就没必要把所有子集都枚举一遍了。

#include <cstdio>
int read()
{
    int sum=0,f=1;char x=getchar();
    while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}
    while(x>='0'&&x<='9'){sum=(sum<<3)+(sum<<1)+x-'0';x=getchar();}
    return sum*f;
}
int n,m,xp[25],f[1030][1030],sn[1030],sm[1030];
int main()
{
    xp[0]=1;for(int i=1;i<=11;i++)xp[i]=xp[i-1]<<1;
    n=read();for(int i=1;i<=n;i++)sn[xp[i-1]]=read();
    m=read();for(int i=1;i<=m;i++)sm[xp[i-1]]=read();
    for(int i=1;i<xp[n];i++)sn[i]=sn[i&-i]+sn[i^(i&-i)];
    for(int i=1;i<xp[m];i++)sm[i]=sm[i&-i]+sm[i^(i&-i)];
    for(int i=1;i<xp[n];i++)
        for(int j=1;j<xp[m];j++)
        {
            for(int k=0;k<n;k++)
                if((xp[k]&i)&&f[i^xp[k]][j]>f[i][j])f[i][j]=f[i^xp[k]][j];
            for(int k=0;k<m;k++)
                if((xp[k]&j)&&f[i][j^xp[k]]>f[i][j])f[i][j]=f[i][j^xp[k]];
            if(sn[i]==sm[j])f[i][j]++;
        }
    printf("%d\n",n+m-2*f[xp[n]-1][xp[m]-1]);
}
The Borg is an immensely powerful race of enhanced humanoids from the delta quadrant of the galaxy. The Borg collective is the term used to describe the group consciousness of the Borg civilization. Each Borg individual is linked to the collective by a sophisticated subspace network that insures each member is given constant supervision and guidance. Your task is to help the Borg (yes, really) by developing a program which helps the Borg to estimate the minimal cost of scanning a maze for the assimilation of aliens hiding in the maze, by moving in north, west, east, and south steps. The tricky thing is that the beginning of the search is conducted by a large group of over 100 individuals. Whenever an alien is assimilated, or at the beginning of the search, the group may split in two or more groups (but their consciousness is still collective.). The cost of searching a maze is defined as the total distance covered by all the groups involved in the search together. That is, if the original group walks five steps, then splits into two groups each walking three steps, the total distance is 11=5+3+3. On the first line of input there is one integer, N <= 50, giving the number of test cases in the input. Each test case starts with a line containing two integers x, y such that 1 <= x, y <= 50. After this, y lines follow, each which x characters. For each character, a space '' stands for an open space, a hash mark#'' stands for an obstructing wall, the capital letter A'' stand for an alien, and the capital letter S'' stands for the start of the search. The perimeter of the maze is always closed, i.e., there is no way to get out from the coordinate of the ``S''. At most 100 aliens are present in the maze, and everyone is reachable. For every test case, output one line containing the minimal cost of a successful search of the maze leaving no aliens alive. 输入样例 2 6 5 ##### #A#A## # # A# #S ## ##### 7 7 ##### #AAA### # A# # S ### # # #AAA### ##### 输出样例 8 11
最新发布
12-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值