画家问题

GitHub跳转原题关系图返回列表

题意与原解析均从本地 OpenJudge 缓存迁移。

OJ: noi_openjudge

题目 ID: ch0201-1815

难度:未知

标签:

日期: 2026-07-30 23:01

题意

完整题面见同目录的 problem.md

思路

代码

cpp
#include <bits/stdc++.h>
using namespace std;

vector<int> opt_list;
const int INF = 0x7fffffff;
int ans = INF;
vector<int> ans_stack(20);
int max_height;
int n;

int wall[20];

void init(){
    scanf("%d",&n);
    if( n == 0) return;
    char str[100];
    int i,j;
    for(i=1;i<=n;i++){
        scanf("%s",str+1);
        int res=0,t = 0;
        for(j=1;j<=n;j++){
            res <<=1;
            if( str[j] == 'y' )
                res |= 1;
        }
        wall[i] = res;

        /* 输出测试 */
        //bitset<15> tmp(wall[i]);
        //cout << tmp << endl;
    }
    /* 生成 opt_list */
    int max_state = (1<<n)-1;
    for(i=max_state;i >0;i = (i-1) &max_state){ // 枚举子集
        opt_list.push_back(i);
    }
    opt_list.push_back(0);

    max_height = (1<<n)-1;
}

/* 计算1的数量 */

int bin_count(int x){
    int cnt = 0;
    x &= max_height;
    for( ; x; x = (x-1) &x){
        cnt++;
    }
    return cnt;
}


void dfs(int dep){

    if( dep == n+1){
        if( (wall[dep-1] & max_height) == max_height ){
            /* 计算结果 */
            int t = 0;
            int i;
            for(i=1;i<=n;i++){
                t += bin_count(ans_stack[i]);
            }
            ans = min(ans,t);
        }
        return ;
    }

    /* 记录 3 行的状态 */
    int up = wall[dep-1];
    int now = wall[dep];
    int down = wall[dep+1];

    /* 推算出操作 */
    int opt = 0;
    int i;
    for(i=0;i<n;i++){
        if( ( (1<<i) & up ) == 0 ){
            opt |= (1<<i);
        }
    }
    opt &= max_height;

    int _up = max_height;
    int _now = ((((opt<<1)^now) ^opt) ^(opt>>1) ) & max_height;
    int _down = ( down ^ opt) & max_height;

    ans_stack[dep] = opt;
    wall[dep-1] = _up;
    wall[dep] = _now;
    wall[dep+1] = _down;
    dfs(dep+1);
    wall[dep-1] = up;
    wall[dep] = now;
    wall[dep+1] = down;

}



int main(){
    init();
    if( n== 0){
        printf("inf");
        return 0;
    }
    /* 枚举第一行的操作 */
    int line_1 = wall[1];
    int line_2 = wall[2];
    reverse(opt_list.begin(), opt_list.end());
    for( auto x : opt_list){
        ans_stack[1] = x;
        wall[1] = ((((x<<1)^line_1 ) ^x) ^(x>>1) ) & max_height;
        wall[2] = (line_2 ^x) & max_height;
        dfs(2);
    }
    if( ans != INF)
        printf("%d",ans);
    else
        printf("inf");
    return 0;
}

复杂度

总结