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

[VIJOS1197] 费解的开关

时间:2019-06-15 10:03:23      阅读:83      评论:0      收藏:0      [点我收藏+]

标签:除了   for   turn   count   return   ace   递推   algo   using   

枚举第一行的点击方案。

则点完后剩余的黑灯只能由第二行同一列的点击来弥补

并且第二行除了弥补第一行的黑灯之外,不能点其他灯,否则会使第一行的灯灭

上述构成了递推关系,则递推到最后一行即可。

二进制位运算优化;注意最后一行的状态的判断

复杂度 \(O(n2^n),n=5\).

代码

#include<cstdio>
#include<algorithm>
using namespace std;
int n;
int fl[10];
int bitcount(int x){// 统计 x 的二进制下 1 的个数
    x=(x&0x55555555)+(x>>1&0x55555555);
    x=(x&0x33333333)+(x>>2&0x33333333);
    x=(x&0x0f0f0f0f)+(x>>4&0x0f0f0f0f);
    x=(x&0x00ff00ff)+(x>>8&0x00ff00ff);
    x=(x&0x0000ffff)+(x>>16&0x0000ffff);
    return x;
}
int main(){scanf("%d",&n);
    while(n--){
        int ans=0x3f3f3f3f;
        for(int i=1;i<=5;i++){fl[i]=0;int a;
            for(int j=1;j<=5;j++)scanf("%1d",&a),fl[i]=fl[i]<<1|(a^1);
        }//input
        for(int i=0;i<32;i++){// 枚举第一行的点击状态
            int s=i,tot=0,t[10];
            for(int j=1;j<=5;j++)t[j]=fl[j];
            for(int j=1;j<=5;j++){// 枚举每一行
                // 当前行的点击状态为 s,则对于下一行的改变为 t[j+1]^s.
                // 对当前行的改变为 t[j] ^ s<<1^s^s>>1 .
                // 这时,当前行剩下的黑灯即为下一行的点击状态
                t[j]=(t[j]^s<<1^s^s>>1)&((1<<5)-1);
                t[j+1]=(t[j+1]^s)&((1<<5)-1);
                tot+=bitcount(s&((1<<5)-1));
                s=t[j];
            }
            if(s==0)ans=min(ans,tot);// 最后一行没有残留的 0
        }
        printf("%d\n",ans>6?-1:ans);
    }
    return 0;
}

[VIJOS1197] 费解的开关

标签:除了   for   turn   count   return   ace   递推   algo   using   

原文地址:https://www.cnblogs.com/sshwy/p/11026350.html

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