BAPC2014 K&&HUNNU11591:Key to Knowledge(中途相遇法)
2015-08-12 23:59
399 查看
题意:
有N个学生,有M题目
然后对应N行分别有一个二进制和一个整数
二进制代表该同学给出的每道题的答案,整数代表该同学的答案与标准答案相符的个数
要求判断标准答案有几个,如果标准答案只有一种,则输出标准答案
思路:
很容易想到状态压缩,但是很明显1<<30纯粹的状压是会超时的,那么我们可以优化一半,变成1<<15
也就是说,对于一个串,我们分半处理
首先处理前一半,讨论前一半与标准答案相符的状况,然后再讨论后半串,看与标准答案相符的情况能不能与前一半相匹配,从而算出答案
有N个学生,有M题目
然后对应N行分别有一个二进制和一个整数
二进制代表该同学给出的每道题的答案,整数代表该同学的答案与标准答案相符的个数
要求判断标准答案有几个,如果标准答案只有一种,则输出标准答案
思路:
很容易想到状态压缩,但是很明显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("\n"); } else printf("%d solutions\n",ans); } return 0; }
相关文章推荐
- 参数寻优:梯度下降/牛顿下降法 追根溯源
- could not build module 'uikit'
- Java当中的反射
- Android:控件WebView显示网页 -摘自网络
- nginx源码分析2———基础数据结构五(ngx_hash_wildcard_t)
- 常见的机器视觉工具(转载)
- 算法和策略之间的混沌关系
- 谈谈对数据库的认识
- @protocol使用讲解
- LeetCode222——Count Complete Tree Nodes
- 机器视觉开源代码集合(转载)
- Codeforces Gym100425 A. Luggage Distribution
- Qt之JSON生成与解析
- POJ 3311 Hie with the Pie 担货郎问题 DP Floyd/Dijkstra + DFS
- 定义一个二维int数组,编写代码获取最小元素
- java的poi技术读取Excel[2003-2007,2010]
- iOS开发学习之自定义cell
- 视图
- PythonProject(1)vim的Hustoj插件
- linux系统的7种运行级别