• Codeforces Round #243 (Div. 2)——Sereja and Table


    看这个问题之前,能够先看看这个论文《一类算法复合的方法》,说白了就是分类讨论,可是这个思想非常重要

    题目链接

    • 题意:
      首先给出联通块的定义:对于相邻(上下和左右)的同样的数字视为一个联通块
      现给一个n*m的仅仅有0和1的矩形和数字k,求出最小反转个数使得总体包含若干个矩形联通块(即每一个联通块均是矩形)(1 ≤ n, m ≤ 100; 1 ≤ k ≤ 10)
      假设最小次数比k大,输出-1

    • 分析:
      题目的特点是k比較小。也就是说反转的次数比較少,所以能够从这里入手。直接枚举全部的位置肯定是不行了,那么能够这样考虑:(最好还是设n>=m)假设n比k大,那么肯定有一些行是不会有反转的数字的,那么我们能够枚举每一行来处理;假设k比n大,这个时候n小于10,所以这时候我们就能够暴力枚举每一行的全部状态。然后处理。


      以上两种方法处理的时候均根据下边的图形特点,仅仅知道一行的时候就能够求出最小的总反转数


    终于仅仅能是
    01010...
    10101...
    ...
    的形状(当中一个字符代表一个矩形)

    const int MAXN = 110;
    
    int ipt[MAXN][MAXN];
    
    int main()
    {
    //    freopen("in.txt", "r", stdin);
    	int n, m, k;
    	while (~RIII(n, m, k))
    	{
    		REP(i, n) REP(j, m) RI(ipt[i][j]);
    		if (n < m)
    		{
    			REP(i, n) FF(j, i + 1, m) swap(ipt[i][j], ipt[j][i]);
    			swap(n, m);
    		}
    		if (n > k)
    		{
    			int ans = INF;
    			REP(i, n)
    			{
    				int tans = 0;
    				REP(j, n)
    				{
    					int cnt = 0;
    					if (i == j) continue;
    					REP(k, m)
    					{
    						if (ipt[i][k] != ipt[j][k]) cnt++;
    					}
    					tans += min(cnt, m - cnt);
    				}
    				ans = min(ans, tans);
    			}
    			printf("%d
    ", ans <= k ? ans: -1);
    		}
    		else
    		{
    			int ans = INF;
    			REP(i, n)
    			{
    				int all = 1 << m;
    				for (int q = 0; q < all; q++)
    				{
    					int diff = 0;
    					for (int t = 0, l = 1; t < m; l <<= 1, t++) if (((q & l) != 0) != ipt[i][t]) diff++;
    					if (diff > k) continue;
    					int tans = 0;
    					REP(j, n)
    					{
    						if (i == j) continue;
    						int cnt = 0;
    						for (int t = 0, l = 1; t < m; t++, l <<= 1) if (((q & l) != 0) != ipt[j][t]) cnt++;
    						tans += min(cnt, m - cnt);
    					}
    					ans = min(ans, diff + tans);
    				}
    			}
    			printf("%d
    ", ans <= k ? ans: -1);
    		}
    	}
    	return 0;
    }
    


    參照大神的代码后的一些细节改动:

    const int MAXN = 110;
    
    int ipt[MAXN][MAXN];
    
    int main()
    {
    //    freopen("in.txt", "r", stdin);
    	int n, m, k;
    	while (~RIII(n, m, k))
    	{
    		int ans = INF, all = 1 << m;
    		REP(i, n) REP(j, m) RI(ipt[i][j]);
    		if (n < m)
    		{
    			REP(i, n) FF(j, i + 1, m) swap(ipt[i][j], ipt[j][i]);
    			swap(n, m);
    		}
    		if (n > k)
    		{
    			REP(i, n)
    			{
    				int tans = 0;
    				REP(j, n)
    				{
    					int cnt = 0;
    					REP(k, m)
    						cnt += ipt[i][k] ^ ipt[j][k];
    					tans += min(cnt, m - cnt);
    				}
    				ans = min(ans, tans);
    			}
    		}
    		else
    		{
    			for (int mask = 0; mask < all; mask++)
    			{
    				int tans = 0;
    				REP(i, n)
    				{
    					int cnt = 0;
    					REP(j, m) cnt += ipt[i][j] ^ (mask >> j & 1);
    					tans += min(cnt, m - cnt);
    				}
    				ans = min(ans, tans);
    			}
    		}
    		printf("%d
    ", ans <= k ? ans: -1);
    	}
    	return 0;
    }




  • 相关阅读:
    jmeter Transaction Controller、Throughput Controller 控制器
    图书系统的简易代码
    模板简单梳理
    自制过滤器
    自制URL转换器
    URL简单梳理
    window下的Django入门
    十一、常用内建模块
    九、进程与线程
    八、错误、调试与测试
  • 原文地址:https://www.cnblogs.com/mthoutai/p/7241352.html
Copyright © 2020-2023  润新知