AcWing 1243. 糖果 ,java同学大体概况
原题链接
中等
作者:
季之秋
,
2021-03-26 22:06:12
,
所有人可见
,
阅读 546
import java.util.*;
public class Main{
static int N=110,M=1<<21;
static int n,m,k;
static ArrayList<Integer>[] col = new ArrayList[N];
static int[] log2 = new int[M];
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
n=sc.nextInt();
m=sc.nextInt();
k=sc.nextInt();
for(int i=0; i<21; i++){ //初始化列表数组/log数组
col[i] = new ArrayList();
log2[1<<i] = i;
}
for(int i=0;i<n;i++){
int state=0;
for(int j=0; j<k; j++){
int t=sc.nextInt();
state |= 1 << t-1; //转化为 k位的二进制,1代表有,0代表没有
}
for(int j=0; j<m; j++){
if(((state >> j) & 1)==1){
col[j].add(state); //哪几行有j列
}
}
}
int depth = 0;
while(depth <= n){ // 从小到大枚举层数
if(dfs(depth, 0)) break; // 找到的第一组解就是最优解
depth++;
}
if(depth > n) System.out.println(-1); // n行,每行至少一个,选n+1行dfs都没有true说明无解,
else System.out.println(depth);
}
static int lowbit(int x){ // 取出最后一位的 1101 0000 = 0001 0000
return x & -x;
}
static int h(int state){ // 自定义下界,即 选包括c列的所有行 ,必定有一条会选,此时就至少选一次
// 所以我们假设全选,全选的情况至少是比最优解还优的,所以作为下界使用,
// 如果比最优解还优的 ,那肯定是没有意义的解
int res=0;
for(int i=(1<<m)-1-state; i!=0; i-=lowbit(i)){
int c = log2[lowbit(i)];
res++;
for(int row : col[c])
i &= ~row;
}
return res;
}
static boolean dfs(int depth,int state){
if (h(state) > depth ) return false; // 比最优解还优解必然是无解的
if(depth == 0 ) return state == (1 << m) - 1; // 终止递归条件
int t = -1; // 选择最少行
for(int i=(1<<m)-1-state; i!=0; i -= lowbit(i)){
int c = log2[lowbit(i)]; // 未选列的下标
if(t<0 || col[t].size() > col[c].size() ) t=c; // 有最少行的列下标
}
for(int row : col[t])
if(dfs(depth - 1, state | row)) return true; //递归看有没有解,有解就true
return false; // 都没有解就false
}
}
超时了,数据加强了