2064: 分裂 状压DP

可以发现状态数很少。当时和现在状态的数任意组合相加可以有2^n个答案。然后似乎可以用f[i][j]表示当时的状态和现在的状态对应的最优答案。转移的话状压似乎也很方便。


然后我又不会了。。。开始认(mo)真(bai)思(ti)考(jie)。。
为什么题解都是只可意会不可言传啊卧槽。。而且都是一维的好厉害的样子。。
不过题解的第一句话瞬间使我脑洞大开QAQ。。操作数上界是n1+n2,如果有两部分和相同那么操作数可以-2。
这样对应回刚才的dp方程就可以解决了。。

为什么每次思考都差那么一点呢。。还是太弱啦。。

#include<iostream>
#include<cstdio>
using namespace std;
int f[1100][1100];
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
struct node 
{
    int n;
    int x[11];
    int sum[1100];
    void dfs(int k,int state,int s)
    {
        if (k==n+1) return;
        sum[state<<(n-k)]=s;
        dfs(k+1,state*2+1,s+x[k+1]);
        dfs(k+1,state*2,s);
    }
}A,B;
int main()
{
    A.n=read();
    for (int i=1;i<=A.n;i++) A.x[i]=read();
    B.n=read();
    for (int i=1;i<=B.n;i++) B.x[i]=read();
    A.dfs(0,0,0); B.dfs(0,0,0);
    for (int i=1;i<(1<<A.n);i++)
        for (int j=1;j<(1<<B.n);j++)
        {
            for (int k=1;k<=A.n;k++)
                if (i&(1<<(k-1))) f[i][j]=max(f[i][j],f[i-(1<<(k-1))][j]);
            for (int k=1;k<=B.n;k++)
                if (j&(1<<(k-1))) f[i][j]=max(f[i][j],f[i][j-(1<<(k-1))]);
            if (A.sum[i]==B.sum[j]) f[i][j]++;
        }
    printf("%d",A.n+B.n-2*f[(1<<A.n)-1][(1<<B.n)-1]);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值