• BAPC2014 K&&HUNNU11591:Key to Knowledge(中途相遇法)


    题意:

    有N个学生。有M题目

    然后相应N行分别有一个二进制和一个整数

    二进制代表该同学给出的每道题的答案。整数代表该同学的答案与标准答案相符的个数

    要求推断标准答案有几个,假设标准答案仅仅有一种。则输出标准答案


    思路:

    非常easy想到状态压缩。可是非常明显1<<30纯粹的状压是会超时的,那么我们能够优化一半,变成1<<15

    也就是说,对于一个串,我们分半处理

    首先处理前一半,讨论前一半与标准答案相符的状况。然后再讨论后半串,看与标准答案相符的情况能不能与前一半相匹配,从而算出答案


    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stack>
    #include <queue>
    #include <map>
    #include <set>
    #include <vector>
    #include <math.h>
    #include <bitset>
    #include <algorithm>
    #include <climits>
    using namespace std;
    
    #define ls 2*i
    #define rs 2*i+1
    #define UP(i,x,y) for(i=x;i<=y;i++)
    #define DOWN(i,x,y) for(i=x;i>=y;i--)
    #define MEM(a,x) memset(a,x,sizeof(a))
    #define W(a) while(a)
    #define gcd(a,b) __gcd(a,b)
    #define LL long long
    #define ULL unsigned long long
    #define N 100005
    #define INF 0x3f3f3f3f
    #define EXP 1e-8
    #define rank rank1
    const int mod = 1000000007;
    
    int t,n,m;
    char str[50][50];
    int a[50];
    LL num[50][2];
    int hsh[1<<16]= {0};
    
    int main()
    {
        int i,j,k;
        for(i = 0; i<(1<<16); i++)//hsh记录1的个数
        {
            t = i;
            while(t)
            {
                hsh[i]+=t%2;
                t/=2;
            }
        }
        scanf("%d",&t);
        while(t--)
        {
            LL ans = 0;
            map<LL,int> cnt;
            map<LL,int> state;
            scanf("%d%d",&n,&m);
            for(i = 0; i<n; i++)
            {
                scanf("%s%d",str[i],&a[i]);
                num[i][0]=num[i][1] = 0;
                for(j = 0; j<m/2; j++)//记录前一半的2进制状态
                    num[i][0] = num[i][0]*2+(str[i][j]-'0');
                for(j = m/2; j<m; j++)//记录后一半的2进制状态
                    num[i][1] = num[i][1]*2+(str[i][j]-'0');
            }
            //前半部的处理
            int s = m/2;
            for(i = 0; i<(1<<s); i++)
            {
                LL tem = 0;
                for(j = 0; j<n; j++)
                {
                    k = hsh[i^num[j][0]];//与答案不同样的个数
                    if(s-k>a[j]) break;
                    tem = tem*30+s-k;//30进制存状态
                }
                if(j==n)
                {
                    cnt[tem]++;//该状态有几种
                    state[tem] = i;
                }
            }
            s = m-s;//后一半
            int s1,s2;
            for(i = 0; i<(1<<s); i++)
            {
                LL tem = 0;
                for(j = 0; j<n; j++)
                {
                    k = hsh[i^num[j][1]];
                    if(s-k>a[j]) break;
                    tem = tem*30+a[j]-(s-k);//找回前一半的状态
                }
                if(j==n&&cnt[tem])
                {
                    ans+=cnt[tem];
                    s1 = state[tem];
                    s2 = i;
                }
            }
            if(ans==1)
            {
                stack<int> Q;
                for(i = 0; i<s; i++)
                {
                    Q.push(s2%2);
                    s2/=2;
                }
                for(i = 0; i<m-s; i++)
                {
                    Q.push(s1%2);
                    s1/=2;
                }
                while(!Q.empty())
                {
                    printf("%d",Q.top());
                    Q.pop();
                }
                printf("
    ");
            }
            else
                printf("%d solutions
    ",ans);
        }
    
        return 0;
    }
    


  • 相关阅读:
    407 Trapping Rain Water II 接雨水 II
    406 Queue Reconstruction by Height 根据身高重建队列
    405 Convert a Number to Hexadecimal 数字转换为十六进制数
    404 Sum of Left Leaves 左叶子之和
    403 Frog Jump 青蛙过河
    402 Remove K Digits 移掉K位数字
    401 Binary Watch 二进制手表
    400 Nth Digit 第N个数字
    398 Random Pick Index 随机数索引
    397 Integer Replacement 整数替换
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/6924480.html
Copyright © 2020-2023  润新知