题目描述
有N(1 <= N <= 20)个杯子,从左往右排成一行,每个杯子要么有一枚硬币,要么没有硬币。
现在有M (1 <= M<= 100)个询问,每个询问的是格式是:由N个0、1组成的序列,表示询问是1的那些杯子中 共有几个杯子是有硬币的?
例如:1000,表示询问第一个杯子中有没有硬币?
0110则表示询问第2、3两个杯子中有几个杯子有硬币?
1001则表示询问第1、4两个杯子中有几个杯子有硬币?
0011则表示第3、4两个杯子中有几个杯子有硬币?
现在你每询问一个问题,你都得到一个答案,当你问完M个问题后,你可以推导出这N个杯子的状态吗?
也就是各个杯子是否有硬币?如果你得到的这M个回答有矛盾,输出IMPOSSIBLE,
如果有多种可能则输出NOT UNIQUE,
否则输出第1、2、..N个杯子的状态,0表示没硬币,1表示有硬币。
输入输出格式
输入格式
第1行:N和M。
第2..M+1行:先是一个01序列,表示询问,然后是你得到的答案。
输出格式
NOT UNIQUE或者IMPOSSIBLE或者一行01序列。
输入输出样例
输入样例
4 5
1000 1
0110 1
1001 1
0011 1
0101 0
输出样例
1010
题解
用二进制的形式来记录杯子的拥有情况,每次枚举所有询问来判断即可。
#include <iostream> #define MAX_N (20 + 5) #define MAX_M (100 + 5) #define LIM ((1 << 20) + 5) #define lowbit(x) ((x) & -(x)) using namespace std; int n, m; int a[MAX_M], c[MAX_M]; int p[LIM]; int lim; int ans = -1; void DFS(int now, int l) { int tmp, nxt = now; int f = 1; for(register int i = 1; i <= m; ++i) { tmp = now & a[i]; if(p[tmp] > c[i]) return; if(p[tmp] < c[i]) f = 0; nxt |= tmp; } if(f) { if(ans == -1) ans = now; else { ans = -2; return; } } nxt = ~nxt & lim; while(nxt) { if(lowbit(nxt) > l) DFS(now + lowbit(nxt), lowbit(nxt));; nxt -= lowbit(nxt); } return; } int main() { cin >> n >> m; lim = (1 << n) - 1; char s[MAX_N]; for(register int i = 1; i <= m; ++i) { cin >> s >> c[i]; for(register int j = 0; j < n; ++j) { a[i] <<= 1; if(s[j] == '1') a[i] |= 1; } } int tmp; for(register int i = 0; i <= lim; ++i) { tmp = i; while(tmp) { ++p[i]; tmp -= lowbit(tmp); } } DFS(0, 0); if(ans == -1) return cout << "IMPOSSIBLE", 0; if(ans == -2) return cout << "NOT UNIQUE", 0; s[n] = 0; for(register int i = n - 1; i >= 0; --i) { s[i] = (ans & 1) + '0'; ans >>= 1; } cout << s; return 0; }