POJ ---- 1222 和 POJ --- 3279 【二进制思维+状态压缩】

POJ1222
题意: 1代表打开, 0关闭, 输出一种方式可以将整个矩阵都关闭.

思路: 我们首先要明白一个事实, 那就是如果第一行的操作确定了, 那么所有的操作就确定下来了, 只要他是可行的. 所以我们直接枚举所有可能, 然后模拟做 , 然后下一行的操作方式就是上一行的状态, 因为亮的必须关闭, 最后判断一下最后一行是不是全关上了就行啦, 注意一些小细节.

然后这个一个字节就行啦, 所以用char存, 省空间.

AC Code:

char orilight[10];   //初始灯的状态.
char result[10];     //结果的操作数.
char light[10];      //中间操作时灯的状态.
int t;
int getbit(int x, int i) {
    return (x >> i) & 1;
}
void filpbit(int &x, int i) { // 翻转x的第i位
    x ^= (1<void setbit(int &x, int i, int c) {
    if (c) x |= (1<else x &= ~(1<void print(int t,char result[])
{
    cout << "PULLZE #" << t << endl;
    for(int i=0;i<5;i++){
        for(int j=0;j<6;j++){
            cout << Getbit(result[i],j);
            if(j<5)
                cout << " " ;
            else
                cout << endl;
        }
    }
}

void solve()
{
    for(int i=0;i<5;i++){
        for(int j=0;j<6;j++){
            int k;
            cin >> k;
                setbit(orilight[i],j,k);
        }
    }
    for(int n=0;n<64;n++){
        memcpy(light,orilight,sizeof(light));
        int switchs=n;  //开关的状态存在switchs中,
            for(int i=0;i<5;i++){
            result[i]=switchs;
            for(int j=0;j<6;j++){      // 对同一行(即第i行)的灯进行处理.
                if(getbit(switchs, j)){
                    if(j>0) flipbit(light[i],j-1);
                    flipbit(light[i],j);
                    if(j < 5) flipbit(light[i],j+1);
                }
            }
            if(i < 4) //因为下一行的操作是根据上一行的状态进行的操作,所以不用再去管上一行.
                light[i+1] ^= switchs; //第i行的操作会影响第i+1行的灯的状态.
            switchs = light[i]; //因为下一行的操作是要根据上一行来进行的,所以需要在把switch再来赋值一波.
                        //因为上一行灯的状态就是下一行的操作状态.
        }
        if(light[4] == 0){
            print(t,result);
            break;
        }
    }
}

与上面那道题的题意一样的,只是这道题的范围变大了而已. 所以我们要用int来存了….
poj — 3279
POJ3279
AC Code

const int maxn = 15+5;
int s[maxn], tmp[maxn], ans[maxn];
int n, m;
int getbit(int x, int i) {
    return (x >> i) & 1;
}
void filpbit(int &x, int i) { // 翻转x的第i位
    x ^= (1<void setbit(int &x, int i, int c) {
    if (c) x |= (1<else x &= ~(1<void solve()
{
    scanf("%d%d", &n, &m);
    for (int i = 1 ; i <= n ; i ++) {
        for (int j = 0 ; j < m ; j ++) {
            int x; scanf("%d", &x);
            setbit(s[i], j, x);
        }
    }
    int flag = 0;
    for (int k = 0 ; k < (1<int sw = k; memcpy(tmp, s, sizeof(tmp));
        for (int i = 1 ; i <= n ; i ++) {
            ans[i] = sw;
            for (int j = 0 ; j < m ; j ++) {
                if (!getbit(sw, j)) continue;
                if (j > 0) filpbit(tmp[i], j-1);
                if (j < m - 1) filpbit(tmp[i], j+1);
                filpbit(tmp[i], j);
            }
            if (i < n) tmp[i+1] ^= sw;
            sw = tmp[i];
        }
        if (!tmp[n]) {
            flag = 1;
            break;
        }
    }
    if (!flag) {
        printf("IMPOSSIBLE\n");
        return ;
    }
    for (int i = 1 ; i <= n ; i ++) {
        for (int j = 0 ; j < m ; j ++) {
            printf("%d%c", getbit(ans[i], j), j == m - 1 ?'\n':' ');
        }
    }
}

你可能感兴趣的:(二进制思维/状压/bitset)