蓝桥杯第十届省赛A组(F)题 (状压DP)

 

本题的m最大也才20.那么就轻松状压DP。

 关于状压DP:

 

因此我们开个vis数组记录需要选几袋,再开个ki数组记录下每种情况状态压缩后的值即可。

AC代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int vis[1<<20],ki[105];
int main(){
    int n,m,k,temp;
    scanf("%d%d%d",&n,&m,&k);
    for(int i=0;i<n;i++){
        int t=0;
        for(int j=0;j<k;j++){
            scanf("%d",&temp);
            t |=(1<<(temp-1));
        }
        vis[t]=1;
        ki[i]=t;
    }
    int que=(1<<m)-1;
    for(int i=1;i<=que;i++)
        if(vis[i])//如果这种情况之前出现过了 
            for(int j=1;j<=n;j++)
                if(vis[i | ki[j]]==0 || vis[i | ki[j]] > vis[i]+1)//如果他们合并所出现的情况没出现过或者出现过但再一次出现时的最小选择数更小 
                    vis[i | ki[j]] = vis[i]+1;//更新 
    if(vis[que])//如果全选的情况能到达 
        printf("%d",vis[que]);
    else
        printf("-1");
}

 

posted @ 2021-03-30 23:01  mikku  阅读(73)  评论(0)    收藏  举报