首先看到这道题的数据范围就可以想到是枚举暴力。
而对于枚举我们有两种方法,一种是 $\texttt{DFS}$,而另一种是通过二进制来进行枚举(反正我用的 $\texttt{DFS}$)。
而这题有两种情况的翻译并没有给出,一种是无解输出 $\texttt{IMPOSSIBLE}$,另一种是解法不唯一输出 $\texttt{NOT UNIQUE}$。
而对于 $\texttt{IMPOSSIBLE}$ 我们只需要判断 $\texttt{DFS}$ 后是否找到了一种解就好了。
对于 $\texttt{NOT UNIQUE}$ 情况我们也只需要在判断是否找到了不唯一的合法解就可以了。
复杂度 $\mathrm{O}(2^{n}m)$,不完全估计 $\mathrm{O}(104857600)$,$\texttt{1s}$ 肯定是能过的啦。
code
#include<bits/stdc++.h>
using namespace std;
int n,m,t[25],ans[25];
bool flag=false,judge;
struct Query{
int a[25];
int num;
}q[105];
bool check(){//判断解是否合法的函数
for(int i=1;i<=m;i++){
int temp=0;
for(int j=1;j<=n;j++){
if(q[i].a[j]&&t[j]){
temp++;//记录搜到的结果的有草料的个数
}
}
if(temp!=q[i].num){//不符合条件直接返回
return false;
}
}
for(int i=1;i<=n;i++){
ans[i]=t[i];
}
if(flag==true){//是否有过合法解
judge=true;
}
return true;
}
void DFS(int dep){
if(dep==n){//搜完n个就检查是否合法
if(check()){
flag=true;
}
return;
}
t[dep+1]=1;//枚举每一种情况
DFS(dep+1);
// if(flag) return;
t[dep+1]=0;
DFS(dep+1);
// if(flag) return;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
char s;
cin>>s;
if(s==' '||s=='\n'){//防止玄学字符串出锅
j--;
continue;
}
q[i].a[j]=s-'0';
}
scanf("%d",&q[i].num);
}
//搜索
t[1]=1;
DFS(1);
t[1]=0;
DFS(1);
if(!flag){
printf("IMPOSSIBLE");
return 0;
}
if(judge){
printf("NOT UNIQUE");
return 0;
}
for(int i=1;i<=n;i++){
printf("%d",ans[i]);
}
return 0;
}