zoukankan      html  css  js  c++  java
  • 【题解】打地鼠 SDOI2011 模拟 行列无关

    Prelude

    为什么洛谷上的题解都是剪枝做的啊!就没有人写复杂度靠谱的算法吗!
    传送到洛谷:( ̄、 ̄)
    传送到BZOJ:( ´・・)ノ(._.`)
    本篇博客地址:o(><;)oo


    Solution

    首先(O(n^6)),或者是(O(n^4 log^2 n))的模拟非常好想,枚举锤子的长宽,然后从左上角开始挨个砸就可以了。
    枚举的复杂度是(O(n^2))的,模拟一次的复杂度是(O(n^4))的,也可以用BIT做到一次模拟(O(n^2 log^2 n))
    仔细想了想发现似乎没法合理枚举,那就只能发掘性质了。
    直觉告诉我似乎是行列无关的。
    具体来说,我们首先固定锤子的长为1,然后枚举锤子的宽,求出当长为1的时候最大可行的宽,叫做(c)
    然后再固定锤子的宽为1,枚举锤子的长,求出当宽为1的时候最大可行的长,叫做(r)
    上面两步可以用(O(n^4))的暴力模拟来做,或者是用BIT做到(O(n^3 log n))
    那么这个(r)(c)就是最终答案。
    试着证明了一下,确实是这样的,具体证明我没有仔细想,大概感觉是从“每个格子被敲打的次数是行列无关的”这条入手?
    然后就A掉了。
    因为我比较懒,所以写的是(O(n^4))的方法,毕竟这个模拟常数小嘛,(O(n^4))过100肯定没问题啦。


    Code

    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    
    using namespace std;
    const int MAXN = 110;
    int _w;
    
    int n, m, a[MAXN][MAXN], tot;
    int r, c, b[MAXN][MAXN];
    int t[MAXN][MAXN];
    
    bool check( int x ) {
    	for( int i = 1; i <= r; ++i )
    		for( int j = 1; j <= c; ++j )
    			t[i][j] = b[i][j];
    	for( int i = 1; i <= r; ++i )
    		for( int j = 1; j <= c-x+1; ++j )
    			for( int k = j+x-1; k >= j; --k )
    				t[i][k] -= t[i][j];
    	for( int i = 1; i <= r; ++i )
    		for( int j = 1; j <= c; ++j )
    			if( t[i][j] ) return false;
    	return true;
    }
    
    void solve() {
    	r = n, c = m;
    	for( int i = 1; i <= r; ++i )
    		for( int j = 1; j <= c; ++j )
    			b[i][j] = a[i][j];
    	for( int x = c; x >= 1; --x )
    		if( check(x) ) {
    			tot /= x;
    			break;
    		}
    	r = m, c = n;
    	for( int i = 1; i <= r; ++i )
    		for( int j = 1; j <= c; ++j )
    			b[i][j] = a[j][i];
    	for( int y = c; y >= 1; --y )
    		if( check(y) ) {
    			tot /= y;
    			break;
    		}
    	printf( "%d
    ", tot );
    }
    
    int main() {
    	_w = scanf( "%d%d", &n, &m );
    	tot = 0;
    	for( int i = 1; i <= n; ++i )
    		for( int j = 1; j <= m; ++j ) {
    			_w = scanf( "%d", &a[i][j] );
    			tot += a[i][j];
    		}
    	solve();
    	return 0;
    }
    
  • 相关阅读:
    BoundsChecker下载
    大型系统内部资源定位的途径
    架构的焦点
    为什么日志只应该有三个级别
    回收站引发ORACLE查询表空间使用缓慢
    题目记录
    广搜入门 待改进的广搜
    归并排序的使用
    大数数组中滚动数组的应用
    多重背包问题
  • 原文地址:https://www.cnblogs.com/mlystdcall/p/8075591.html
Copyright © 2011-2022 走看看