挑战程序设计竞赛 2章习题 Aizu - 0525 Osenbei BFS

地址 https://vjudge.net/problem/Aizu-0525


IOI 糖果公司使用自公司成立以来一直沿用的传统方法烘烤米果。 这种传统方法是将米果的正面用炭火烘烤一段时间,正面烤好后将其翻面,再将背面用炭火烘烤一段时间。 在保持这一传统的同时,米果是用机器烘烤的。 机器烘烤的米果呈长方形,纵行为 R(1≤R≤10),横列为 C(1≤C≤10000)。

正常情况下,机器自动运行,当正面烘烤完成后,机器同时将米果翻转过来,烘烤背面。
有一天,在烘烤米饼时,就在米饼翻面之前发生了地震,导致部分米饼被翻面。

幸运的是,炭火依然完好,但如果再烘烤正面,烘烤时间就会超过公司成立以来的传统规定,米果的正面就会烧焦,无法作为产品出厂。

因此,匆忙将机器改为手动操作,只翻转尚未翻转的米果。 该机器可以同时翻转横排和竖列,但遗憾的是,它不能逐个翻转米果。
如果翻转米果的时间过长,地震时未翻转的米果正面就会过熟,无法作为产品出厂。

横排也要翻面一次。 还要考虑没有横行被翻转或没有竖列被翻转的情况。 请编写一个程序,输出可装运的米果的最大数量。
假设地震发生后,米果立即处于下图所示的状态。 黑圈表示正面烧焦,白圈表示背面烧焦。


多组数据 以输入 0 0 结束
1 ≤ R ≤ 10, 1 ≤ C ≤ 10 000
入力例
2 5
0 1 0 1 0
1 0 0 0 1
3 6
1 0 0 0 1 0
1 1 1 0 1 0
1 0 1 1 0 1  
0 0
出力例
9
15

解答

 

查看数据范围

以每行是否翻转作为状态,那么一共有210状态就是1024个

每列是否翻转取决于每列上0多还是1多

所以我们遍历每行是否翻转的状态, 然后按照每列最多的0或者1的数目累加 就是能够得到的最多0的数目

使用位运算记录每行是否已经翻转  

// 112355555.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <unordered_set>
#include <algorithm>

using namespace std;


/*
入力例
2 5
0 1 0 1 0
1 0 0 0 1
3 6
1 0 0 0 1 0
1 1 1 0 1 0
1 0 1 1 0 1
0 0
出力例
9
15

//==============
3 22
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
3 22
1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
3 22
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
3 22
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1
1 1 1 1 1 0 1 1 1 1 1 0 1 0 1 1 1 1 1 1 1 1
3 22
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1
1 1 1 1 1 0 1 1 1 1 1 0 1 0 1 0 1 1 1 1 1 1
9 22
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1
1 1 1 1 1 0 1 1 1 1 1 0 1 0 1 0 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1
1 1 1 1 1 0 1 1 1 1 1 0 1 0 1 0 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1
1 1 1 1 1 0 1 1 1 1 1 0 1 0 1 0 1 1 1 1 1 1
0 0
*/

const int N = 100010;
int arr[20][N];

int c, r;
int ans = 0;

unordered_set<int> ss;

//第i行翻转1次
void Reverse(int idx) {
    for (int i = 0; i < r; i++) {
        arr[idx][i] ^= 1;
    }
}

int calc()
{
    int sum = 0;
    //逐列计算0 1的个数 取个数多的加上
    for (int i = 0; i < r; i++) {
        int One_Count = 0; int Zero_Count = 0;
        for (int j = 0; j < c; j++) {
            if (arr[j][i] == 1) One_Count++;
            else Zero_Count++;
        }
        sum += max(One_Count, Zero_Count);
    }

    return sum;
}


void dfs(int reverIdx)
{
    ans = max(ans, calc());

    for (int i = 0; i < c; i++) {
        int tmp = reverIdx ^ (1 << i);
        if (ss.count(tmp) == 0) {
            ss.insert(tmp);
            //没尝试过的都 进行计算
            Reverse(i);
            //计算得到最多的0
            ans = max(ans, calc());
            dfs(tmp);
            Reverse(i);
        }
    }
}


int main()
{
    while (1) {
        cin >> c >> r;
        ans = 0; ss.clear();
        if (c == 0 && r == 0) break;

        for (int i = 0; i < c; i++) {
            for (int j = 0; j < r; j++) {
                cin >> arr[i][j];
            }
        }

        dfs(0);
        cout << ans << endl;
    }

    return 0;
}

 

 


#include <iostream>


using namespace std;


int
r, c; int gra[15][10010]; int ans = -1; void flip(int row) { for (int j = 0; j < c; j++) { gra[row][j] ^= 1;} } void reflip(int row) { flip(row); } void Check() { int sum = 0; for (int i = 0; i < c; i++) { int a = 0; int b = 0; for (int j = 0; j < r; j++) { if (gra[j][i] == 1) {a++;} else {b++;} } sum += max(a, b); } ans = max(sum, ans); } void dfs(int curr) { if (curr >= r) { //检验当前的 Check(); return; } //当前 选择或者不选择 flip(curr); dfs(curr + 1); reflip(curr); dfs(curr+1); return; } void solve() { ans = -1; dfs(0); cout << ans << endl; return ; } int main() { while (cin >> r >> c) { if (r == 0 && c == 0) break; for (int i = 0; i < r; i++) { for (int j = 0; j < c; j++) { cin >> gra[i][j]; } } solve(); } return 0; }

 

posted on 2021-03-20 17:54  itdef  阅读(60)  评论(0编辑  收藏  举报

导航