poj 1903 Jurassic Remains 中途相遇法

中途相遇法就是 2^n种状态 不全部枚举 先枚举2^*(n/2)个状态 再枚举后 n/2个 2^(n/2)种转态 再与前面 2^(n/2)个相匹配这样复杂度会降很多,二分的思想

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
map<int, int> cnt, sym;
int cnt2[11000], sym2[11000];
int a[1000], n , b[1000];
char s[2000];
void dfs1(int pre,int va,int sum,int n,int la)
{
     if(sum > cnt[va]){
        cnt[va] = sum;
        sym[va] = pre;
     }
     for(int i = la; i < n; i++)
        if(!(pre & (1<<i))){
        dfs1(pre | (1<<i), va^a[i], sum+1, n, i + 1);
     }
}
void dfs2(int pre,int va,int sum,int n,int la)
{
     cnt2[pre] = sum;
     sym2[pre] = va;
     for(int i = la; i < n; i++)
        if(!(pre & (1<<i))){
        dfs2(pre | (1<<i), va^b[i], sum+1, n, i + 1);
     }
}
int main()
{
    while(scanf("%d", &n)!=EOF)
    {
        cnt.clear();
        memset(cnt2,0,sizeof(cnt2));
        sym.clear();
        memset(sym2,0,sizeof(sym2));
        int n1 = n/2, n2 = n - n1;
        for(int i = 0; i < n1; i++)
        {
            scanf("%s", s);
            a[i] = 0;
            for(int j = 0; s[j]; j++) a[i] ^= (1 << (s[j] - 'A'));
        }
        for(int i = 0; i < n2; i++)
        {
            scanf("%s", s);
            b[i] = 0;
            for(int j = 0; s[j]; j++) b[i] ^= (1 << (s[j] - 'A'));
        }

        dfs1(0, 0, 0, n1, 0);
        dfs2(0, 0, 0, n2, 0);

        int ansCnt = 0,ans = 0;
        int la = (1<<n2);
        for(int i = 0; i < la; i++)
        {
            int o = sym2[i];
            int pre = cnt[o];
            int oo = cnt2[i];
            if(pre != 0 || o == 0 )
            {
               if(pre + oo > ansCnt)
               {
                   ansCnt = pre + oo;
                   ans = (sym[o]|(i<<n1));
               }
            }
        }
        printf("%d\n", ansCnt);
        int sum = 1;
        bool sym = true;
        while(ans)
        {
            if(ans & 1)printf("%d ",sum);
            ans >>= 1;
            sum++;
        }
        printf("\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值