最后更新于
dp[j | data[i]] = dp[j] + 1;public static void main(String[] args) {
int n,m,k;
Scanner sc = new Scanner(System.in);
n = sc.nextInt(); m = sc.nextInt(); k = sc.nextInt();
int[] data = new int[n];
int[] dp = new int[1<<k];
//初始化,全初始为-1表示没算过不存在,除了起点
Arrays.fill(dp, -1); dp[0] = 0;
for(int i =1; i<=n; i++) {
for(int j = 1;j<=k;j++) {
//读入数据,并以二进制数表示
data[i] = data[i] | (1 << (sc.nextInt()-1));
//这里1 << (sc.nextInt()-1) 即构建二进制表示的过程
//如输入为3,则1左移2位,变为100,表示只选第三个包裹
}
//顺手把只选取这个包裹里的糖果种类的状态的dp设为1
//因为只选取这个包裹里的糖果种类自然只需要拿1次这个包裹就行了
dp[data[i]] = 1;
}
//开始dp
for(int i=1;i<=n;i++) { //依次针对每个包裹分析
for(int j =0;j<(1<<m);j++) { //针对每种状态分析
//注意这里for的边界条件是1<<m,之前读数据二进制的时候是1<<(x-1)
//1<<m其实有m+1位,所以这里所有数都小于1<<m,且正好小于。
if(dp[j]== -1)continue; //状态不存在的时候跳过,因为是从下往上推,不存在就没法推
//下面是其转移的目标的情况分析
//1. 目标状态不存在,直接算出目标的dp值
//2.目标状态存在,需要判断我们推的值能不能小于已有dp值,如果小于则替换
if(dp[j | data[i]] == -1 || dp[j] +1 < dp[j|data[i]])
dp[j|data[i]] = dp[j] +1; //这里j|data[i]是原来j状态用了i包裹而推算出的目标状态
}
}
System.out.println(dp[(1 << m) - 1]); //输出111..11状态的值
}