Gym 101512K

来源:互联网 发布:office mac 破解 威锋 编辑:程序博客网 时间:2024/05/16 14:33
/*************************************************************************    > Author: MentalOmega    > Mail: 965194745@qq.com    > Created Time: 2017年9月24日    > function:这道题的意思是给出n(n<=12)个学生提交的选择题答案,并且附上老师改出来的分数,然后问题是    正确答案有多少种(可能有多种答案改出来的分数是一样的)。如果是直接暴力枚举答案有2的30次方那么多种答案    时间复杂度不够。这里用了一个很巧妙的方法,就是双向搜索,先枚举一半的答案,然后算出每个学生另一半选择题还差多少分,这个    可以压缩在一个map中记录起来,然后枚举另一半答案,如果check出来的分数正是前一半所需要的,就能把方案数加起来了 ************************************************************************/#include<bits/stdc++.h>using namespace std;string ans[15];int grade[15];int main(){    if (fopen("in.txt", "r") != NULL)    {        freopen("in.txt", "r", stdin);        // freopen("out.txt", "w", stdout);    }    ios::sync_with_stdio(0);    cin.tie(0);    int t;    cin>>t;    while(t--)    {        map<string,pair<int,long long>> rec;        int n,m;        cin>>n>>m;        for(int i=0;i<n;i++)        {            cin>>ans[i]>>grade[i];        }        int mid=m/2;        for(long long a=0;a<1ll<<mid;a++)//处理前半段        {            string status="";            for(int i=0;i<n;i++)            {                int p=0;                long long aa=a;                for(int j=0;j<mid;j++)                {                    if((aa&1)==ans[i][j]-'0') p++;                    aa>>=1;                }                int relase=grade[i]-p;                if(relase<0) break;                status+='0'+relase;            }            if(status.size()==n)            {                rec[status].first++;                rec[status].second=a;            }        }        long long solution=0;        long long left,right;        for(long long a=0;a<1ll<<(m-mid);a++)//处理后半段        {            string status="";            for(int i=0;i<n;i++)            {                int p=0;                long long aa=a;                for(int j=mid;j<m;j++)                {                    int nb=ans[i][j]-'0';                    if((aa&1)==nb) p++;                    aa>>=1;                }                int relase=grade[i]-p;                if(relase<0) break;                status+='0'+p;            }            if(status.size()==n)            {                auto it=rec.find(status);                if(it!=rec.end())                {                    solution+=it->second.first;                    left=it->second.second;                    right=a;                }            }        }        if(solution==1)        {            string ans="";            for(int i=0;i<mid;i++)            {                ans+='0'+(left&1);                left>>=1;            }            for(int i=mid;i<m;i++)            {                ans+='0'+(right&1);                right>>=1;            }            cout<<ans<<'\n';        }        else        {            cout<<solution<<" solutions\n";        }    }    return 0;}
原创粉丝点击