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

挑战程序设计竞赛2.1习题:Osenbei Aizu - 0525

时间:2020-01-15 16:46:55      阅读:76      评论:0      收藏:0      [点我收藏+]

标签:scanf   操作   糖果   color   整数   最大值   商品   而且   amp   

おせんべい

問題

IOI製菓では,創業以来の伝統の製法で煎餅(せんべい)を焼いている.この伝統の製法は,炭火で一定時間表側を焼き,表側が焼けると裏返して,炭火で一定時間裏側を焼くというものである.この伝統を守りつつ,煎餅を機械で焼いている.この機械は縦 R (1 ≤ R ≤ 10) 行, 横 C (1 ≤ C ≤ 10000) 列の長方形状に煎餅を並べて焼く.通常は自動運転で,表側が焼けたら一斉に煎餅を裏返し裏側を焼く.

ある日,煎餅を焼いていると,煎餅を裏返す直前に地震が起こり何枚かの煎餅が裏返ってしまった.幸いなことに炭火の状態は適切なままであったが,これ以上表側を焼くと創業以来の伝統で定められている焼き時間を超えてしまい,煎餅の表側が焼けすぎて商品として出荷できなくなる.そこで,急いで機械をマニュアル操作に変更し,まだ裏返っていない煎餅だけを裏返そうとした.この機械は,横の行を何行か同時に裏返したり縦の列を何列か同時に裏返したりすることはできるが,残念なことに,煎餅を1枚ごと裏返すことはできない.

裏返すのに時間がかかると,地震で裏返らなかった煎餅の表側が焼けすぎて商品として出荷できなくなるので,横の何行かを同時に1回裏返し,引き続き,縦の何列かを同時に1回裏返して,表側を焼きすぎずに両面を焼くことのできる煎餅,つまり,「出荷できる煎餅」の枚数をなるべく多くすることにした.横の行を1行も裏返さない,あるいは,縦の列を1列も裏返さない場合も考えることにする.出荷できる煎餅の枚数の最大値を出力するプログラムを書きなさい.

地震の直後に,煎餅が次の図のような状態になったとする.黒い丸が表側が焼ける状態を,白い丸が裏側が焼ける状態を表している.

技术图片

1行目を裏返すと次の図のような状態になる.

技术图片

さらに, 1列目と5列目を裏返すと次の図のような状態になる.この状態では,出荷できる煎餅は9枚である.

技术图片

ヒント

R の上限 10 は C の上限 10000 に比べて小さいことに注意せよ.

入力

入力は複数のデータセットからなる.各データセットは以下の形式で与えられる.

入力の1行目には2つの整数 R, C (1 ≤ R ≤ 10, 1 ≤ C ≤ 10 000) が空白を区切りとして書かれている.続く R 行は地震直後の煎餅の状態を表す. (i+1) 行目 (1 ≤ i ≤ R) には, C 個の整数 ai,1, ai,2, ……, ai,C が空白を区切りとして書かれており, ai,j は i 行 j 列 の煎餅の状態を表している. ai,j が 1 なら表側が焼けることを, 0 なら裏側が焼けることを表す.

C, R がともに 0 のとき入力の終了を示す. データセットの数は 5 を超えない.

出力

データセットごとに,出荷できる煎餅の最大枚数を1行に出力する.

入出力例

入力例

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

大米饼干
问题
自成立以来,IOI糖果就使用传统食谱烤制米饼。在这种传统方法中,将正面用木炭烘烤一定时间,然后在烘烤正面时翻过来,然后用木炭将背面烘烤一定时间。在保持这一传统的同时,用机器烤米饼。本机将米饼烘烤成R行(1≤R≤10)行和C列(1≤C≤10000)行的矩形排列。通常,当正面被烧时,米饼同时被翻转,背面被烘烤。

一天,在烘烤薄脆饼干的过程中,刚好在翻脆薄脆饼干之前发生了地震,还翻了几只薄脆饼干。幸运的是,木炭燃烧的条件仍然合适,但是,如果再对正面进行烘烤,则将超过自其成立以来传统所规定的烘烤时间,并且米饼的正面会变得太热而无法作为产品运输。因此,他迅速将机器更改为手动操作,并试图只交还未交接的米果饼干。该机器可以同时翻转几行或同时翻转几列,但不幸的是,它不能一次翻转一个糯米饼。

如果需要时间将其翻转,那么由于地震未翻转的糯米饼的正面将变得太热而无法作为产品运输,因此一些水平行将同时翻转一次,然后一些垂直行将同时翻转一次。因此,我们决定在不过度烘烤正面的情况下增加可以在两侧烘烤的仙贝的数量,即可以运送的仙贝的数量。考虑以下情况:没有水平行被翻转,或者没有垂直列被翻转。编写一个程序,输出可以运输的最大数量的米果饼干。

地震发生后,糯米饼立即处于下图所示的状态。黑色圆圈表示正面在燃烧,白色圆圈表示背面在燃烧。

技术图片
如果翻转第一行,将看到下图。

技术图片


另外,如果翻转第一和第五列,您将看到下图。在这种状态下,可以运送9个大米饼干。

技术图片


提示
请注意,R的上限10小于C的上限10000。

输入项
输入包含多个数据集。每个数据集都以以下格式给出。

输入的第一行包含两个由空格隔开的整数R和C(1≤R≤10,1≤C≤10000)。接下来的R行显示了地震后立即爆米花的状态。在第(i +1)行(1≤i≤R)中,C个整数ai,1,ai,2,……,ai,C隔开一个空格,ai,j为i它在第j列和第j列中表示饼干的状态,如果ai,j为1,则烘焙正面,如果为0,则烘焙背面。

当C和R均为0时,表示输入结束,数据集数不超过5。

输出量
对于每个数据集,可以在一行上输出可以运输的大米饼干的最大数量。

输入/输出示例
输入例
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

口嗨证明可行性,不管先翻横还是竖,改变翻的顺序并不会改变最终结果,而且同一根棍子翻偶数次等于不翻,奇数次等于一次。横行的数量很小(可以递归),然后所有行翻转递归完了可以统计每一列,如果每一列想要保留的小于不保留的,那就翻转那一列就OK了,所以我们只用统计每一列最多的一种的数量再次累加即可得到所有行翻转的情况下每一种的最大保留数,然后再其中取最大就是最大的保留情况了。本题精明之处在于确定了行翻转的情况之后,最大保留值是确定的(因为列要么翻,要么不翻,肯定是该列要保留的饼多于不保留的才不翻),所以只要确定行翻转就能得到该情况的最大,在遍历所有的行翻转情况,就能得到所有情况的最大值。

思路借鉴:https://blog.csdn.net/Jason_crawford/article/details/53339366

AC代码:

 

#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
int n, m;
int a[15][10005];
int ans;
void dfs(int line)
{
    if(line == m)
    {
        int sum = 0;
        for(int i = 0; i < n; i++)
        {
            int tsum = 0; 
            for(int j = 0; j < m; j++)
            {
                if(a[j][i])
                    tsum++;
            }
            sum += max(tsum, m - tsum);
        }
        ans = max(ans, sum);
        return;
    }
    dfs(line + 1);
    for(int i = 0; i < n; i++)
        a[line][i] = !a[line][i];
    dfs(line + 1);
}
int main(void)
{
    while(scanf("%d %d", &m, &n) && (m != 0 || n != 0))
    {
        ans = 0;
        for(int i = 0; i < m; i++)
            for(int j = 0; j < n; j++)
                scanf("%d", &a[i][j]);
        dfs(0);
        printf("%d\n", ans);
    }
    return 0;
}

挑战程序设计竞赛2.1习题:Osenbei Aizu - 0525

标签:scanf   操作   糖果   color   整数   最大值   商品   而且   amp   

原文地址:https://www.cnblogs.com/jacobfun/p/12197438.html

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