码迷,mamicode.com
首页 > 其他好文 > 详细

关灯问题II 状压DP

时间:2019-11-09 23:38:02      阅读:93      评论:0      收藏:0      [点我收藏+]

标签:开始   efi   --   block   print   turn   ==   不同   ring   

关灯问题II 状压DP

\(n\)个灯,\(m\)个按钮,每个按钮都会对每个灯有不同影响,问最少多少次使灯熄完。

\(n\le 10,m\le 100\)

状压DP的好题,体现了状压的基本套路与二进制操作

注意到此题\(n\)极小,一般小于\(16\)就可以做状压,并且发现每次转移时需要每盏灯的信息,于是我们直接将灯状态塞进二进制即可。

首先我们从初态开始按顺序枚举状态,然后枚举每次状态的决策,最后按题意转移到下一个状态即可。

#include <cstdio>
#include <algorithm>
#include <cstring>
#define MAXN 11
#define MAXM 110
using namespace std;
int n,m;
int a[MAXM][MAXN];
int f[1<<10];
int main(){
    scanf("%d%d", &n, &m);
    int mxf=(1<<n)-1;
    for(int i=1;i<=m;++i)
        for(int j=1;j<=n;++j)
            scanf("%d", &a[i][j]);
    memset(f, 0x3f, sizeof f);
    f[mxf]=0;
    for(int i=mxf;i>=0;--i){
        for(int j=1;j<=m;++j){
            int to=i;
            for(int k=1;k<=n;++k){
                if(a[j][k]==0) continue;
                if(a[j][k]==1 && (to & (1<<(k-1))) ) to=to^(1<<(k-1));
                if(a[j][k]==-1 && !(to & (1<<(k-1))) ) to=to^(1<<(k-1));
            }
            f[to]=min(f[i]+1, f[to]);
        }
    }
    if(f[0]==0x3f3f3f3f) puts("-1");
    else printf("%d\n", f[0]);
    return 0;
}

关灯问题II 状压DP

标签:开始   efi   --   block   print   turn   ==   不同   ring   

原文地址:https://www.cnblogs.com/santiego/p/11828217.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!