当前位置: 代码迷 >> 综合 >> POJ-2965-The Pilots Brothers' refrigerator
  详细解决方案

POJ-2965-The Pilots Brothers' refrigerator

热度:50   发布时间:2023-12-19 11:49:36.0

今晚上做了2965,做法和1753差不多,毕竟在POJ训练计划上都是属于一样的题目,枚举

代码就不重复了,和1753差不了多少。后来我在网上搜了这道题目,竟然发现有个大神竟然出来了一个很简单的算法。

真是厉害,看样子找规律很重要啊!!!!

作者网址:http://www.cppblog.com/Yusi-Xiao/archive/2010/07/05/77385.html
他的思路是:

先看一个简单的问题,如何把'+'变成'-'而不改变其他位置上的状态?
 答案是将该位置(i,j)及位置所在的行(i)和列(j)上所有的handle更新一次。
 结果该位置被更新了7次,相应行(i)和列(j)的handle被更新了4次,剩下的被更新了2次.
 被更新偶数次的handle不会造成最终状态的改变.
 因此得出高效解法,在每次输入碰到'+'的时候, 计算所在行和列的需要改变的次数
 当输入结束后,遍历数组,所有为奇数的位置则是操作的位置,而奇数位置的个数之和则是最终的操作次数.

再看他的代码

:

#include <stdio.h>
#define Len 4
void main()
{
    int handles[Len][Len] = {0};
    int  i, j, k, step = 0;
    char c;
   
    // 核心算法,统计翻转的总次数
    for (i = 0; i < Len; ++i)
    {
        for (j = 0; j < Len; ++j)
       {
           scanf("%c", &c);
            if ('+' == c)
            {
                handles[i][j]++;
                for (k = 0; k < Len; ++k)
                {
                    handles[i][k]++;            // 这种算法重复计算i,j 处,但是对于只需要判断奇偶来说无所谓
                   handles[k][j]++;
                }
            }
        }
  getchar();//一开始的代码这位大神竟然没有接受\n,也不知道因为什么!
    }
    // 统计奇数的个数
    for (i = 0; i < Len; ++i)
    {
        for (j = 0; j < Len; ++j)
        {
            if (handles[i][j] % 2)
            {
                step++;
            }
        }
    }
    printf("%d\n", step);
   
    // 打印奇数的位置
    for (i = 0; i < Len; ++i)
    {
        for (j = 0; j < Len; ++j)
        {
            if (handles[i][j] % 2)
            {
               printf("%d %d\n", i + 1, j + 1);
            }
        }
    }
}