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

CodeForces 449A - Jzzhu and Chocolate

时间:2014-09-23 15:45:04      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   io   os   ar   strong   

传送门:Jzzhu and Chocolate

 

题意:

  给出一个N * M的矩阵,给K个操作,每次操作可以横/竖切割矩阵,最后求K次切割之后,矩阵最小的那块面积最大是多少?

 

分析:

  按照题意,题目求的结果是:(最小的面积,最大是多少),那么可以想到,K次切割之后尽量使得每个块的面积相等,某些块比较大(因为不一定能平均分),那么就可以使得最小的那块面积最大了。

 

  然后如何切割呢?

 

  因为有横竖两个切割方法,那么我们可以设X为横切割数,Y为竖切割数,其中(0 <= X, Y <= K,因为最多对一个方向切割K次,最少不切割,就是0了。这个范围很重要。

 

  按照上面分析的, K次切割之后尽量使得每个块的面积相等),首先只对其中一个方向来看,尽量相等,那么我们可以不管剩下不想等的了,因为肯定比其他大,就不是我们想要的最小那块,那么根据整除的性质,设最后横竖剩下的那块大小为A * B 那么就有

  A = N / (X + 1);   (为什么是X + 1, 因为切了X次之后,就肯定有X+1份,那么求平均大小,就是除X+1)

  B = M / (Y + 1);

 

  注意,上面是整除,也可以写成:

 

  A = floor(N / (X + 1)); 

  B = floor(M / (Y + 1));

 

  那么得到A * B 最大,就是

 

  =>    A * B = floor(N / (X + 1)) * floor(M / (Y + 1)); 最大

  暂时忽略整除性质(这个很重要,但是推导公式的时候,可以先忽略,因为不会影响推导)。

 

  =>    A * B = N / (X + 1) * M / (Y + 1);

 

  要使得上面A * B 最大,那么就是 N / (X + 1) * M / (Y + 1) 最大就好了

 

  =>    A * B = (N * M) / ((X + 1) * (Y + 1))

 

  因为N, M为已知数,使得方程组最大,分子固定,那么只需要分母最小就好了。

 

  现在就转化成为求(X + 1) * (Y + 1)如何情况下最小。

 

  因为X + Y == K,这里可以看出来,横竖必须要满足可以切割K

 

  而又因为假如有N个格子,最多切N - 1次,所以可以得到判定式

  =>    如果  N - 1 + M - 1 < K  那么最后是切不完的,结果就是 -1

 

  由(X + 1) * (Y + 1) X + Y == K可以得到,新的方程式是:

  =>    (X + 1) * (K - X + 1)

 

  设FX= (X + 1) * (K - X + 1) 最小,现在就是求FX)最小的问题了,

  =>    FX = -X ^ 2 + K * X + K + 1 0 <= X <= K)(0 <= X <= N

 

  这个是一元二次方程组,其中K为已知(题目给了)

 

  最后就是求解这个方程组的最小值问题了。

  学过数学的都知道,这个方程组的开口向下

 

  由于X的范围是[0 K],现在要讨论KN的关系了

 

  (1    如果  K <= N - 1(为什么是N - 1, 因为如果要把一个面切成N份,只需要切N-1次就可以了),那么就是可以在N上切K次,

 

  由于方程式的性质(开头向下的一元二次方程),那么容易想到要使得FX)最小,只有两个点,

 

  1. X == 0 这个时候FX)跟y轴相交

 

  2. 因为对于XFX)在y轴线右边是单调递减的,所以如果要使得FX)最小,X取最大值就可以了,所以X == K

 

  那么第一种情况下,X == K就是解(简单吧?)

  X == K的话,那么Y == 0

  所以A * B == floor(N / (K + 1)) * floor(M / (0 + 1))

 

  因为现在假设的是横切K次,有可能列切K次才是最优结果,那么就做两次再对比咯

 

  A * B == floor(M / (K + 1)) * floor(N / (0 + 1))

 

  两个结果取最大值就行了。

 

  (2    如果 K > N - 1,那么就要讨论如何切割了。

 

  还是那个方程式 FX = -X^2 + K * X + K + 1 0 <= X <= K)(0 <= X <= N

  1. X == 0 这个时候FX)跟y轴相交

  2. 因为对于XFX)在y轴线右边是单调递减的,所以如果要使得FX)最小,X取最大值就可以了,最大值就是N,但是不能切N次,所以取N - 1 N - 1次就可以把整块切成N份了)

 

  那么第二种情况下,X == N - 1就是解

  X == N - 1的话,那么Y == K - N - 1

 

  所以A * B == floor(N / ((N - 1) + 1)) * floor(M / ((K - (N - 1)) + 1))

   

  因为现在假设的是横切K次,有可能列切K次才是最优结果,那么就做两次再对比咯

 

  A * B == floor(M / ((M - 1) + 1)) * floor(N / ((K - (M - 1)) + 1))

 

  两个结果取最大值就行了。

 

代码如下:

  1 #ifndef ONLINE_JUDGE
  2 #define __DEBUG__ 0
  3 #endif
  4 
  5 /*
  6  * =======================================
  7  *    FileName: code.cpp
  8  *        Desc: 
  9  *      Author: vinceliang
 10  *       Email: liangguoqiu@gmail.com
 11  *    HomePage: 
 12  *     Version: 0.0.1
 13  *  LastChange: 2014-07-15 12:16:49
 14  *     History:
 15  *========================================
 16  */
 17 
 18 
 19 
 20 #ifdef __DEBUG__
 21 #define Log(...) printf(__VA_ARGS__)
 22 #else
 23 #define Log(...) //
 24 #endif
 25 
 26 #include <algorithm>
 27 #include <string>
 28 #include <complex>
 29 #include <cassert>
 30 #include <memory>
 31 #include <set>
 32 #include <stack>
 33 #include <map>
 34 #include <list>
 35 #include <deque>
 36 #include <numeric>
 37 #include <cctype>
 38 #include <cstddef>
 39 #include <vector>
 40 #include <queue>
 41 #include <iostream>
 42 #include <iomanip>
 43 #include <iterator>
 44 #include <cmath>
 45 #include <cstdio>
 46 #include <cstdlib>
 47 #include <sstream>
 48 #include <fstream>
 49 #include <ctime>
 50 #include <cstring>
 51 #include <functional>
 52 #include <bitset>
 53 
 54 using namespace std;
 55 
 56 #if defined(_MSC_VER) || defined(__BORLANDC__)
 57 typedef unsigned __int64 uint64;
 58 typedef unsigned __int64 ULL;
 59 typedef signed __int64 int64;
 60 typedef signed __int64 LL;
 61 #else
 62 typedef unsigned long long uint64;
 63 typedef unsigned long long ULL;
 64 typedef signed long long int64;
 65 typedef signed long long LL;
 66 #endif
 67 
 68 typedef vector<int> VI;
 69 typedef vector<string> VS;
 70 typedef pair<int, int> PII;
 71 typedef pair<int64, int64> PLL;
 72 typedef vector<int64> VL;
 73 
 74 #define pb push_back
 75 #define pob pop_back
 76 #define mp make_pair
 77 #define fi first
 78 #define se second
 79 
 80 #define PII pair< int,int >
 81 #define PSS pair< string,string >
 82 #define PDD pair< double,double >
 83 #define PLL pair< LL, LL >
 84 
 85 #define FOR( i, a, b ) for ( int i=(a), _n=(b); i < _n; ++i )
 86 #define FORE( i, a, b ) for ( int i=(a), _n=(b); i <= _n; ++i )
 87 #define FORD( i, a, b ) for ( int i=(a), _n=(b); i >= _n; --i )
 88 
 89 #define REP( i, n ) FOR( i, 0, (n) )
 90 #define REPE( i, n ) FORE( i, 1, (n) )
 91 
 92 #define ALL( c ) (c).begin(), (c).end()
 93 #define SORT( c ) sort( ALL( c ) )
 94 #define LEN( s ) (int)( (s).size() )
 95 #define CLS( a ) memset( (a),0,sizeof(a) )
 96 
 97 #define IOS ios::sync_with_stdio( false ) 
 98 
 99 const double PI = 3.1415926535897932384626433832795028841971;
100 const double EPS = 1E-9;
101 const int64 INF64 = (int64)1E18;
102 const int INF = 1 << 30;
103 const int maxn = 1005;
104 
105 LL fun( LL iMax, LL iMin, LL k )
106 {
107     LL Area = -1;
108     if ( iMax > k ) 
109     {
110         Area = ( iMax / (k + 1) ) * iMin;
111     }
112     else 
113     {
114         LL leftK = k - (iMax - 1);
115         if ( iMin > leftK )
116         {
117             Area = ( iMin / ( leftK + 1 ) );
118         }
119         else
120         {
121             Area = -1;
122         }
123     }
124     return Area;
125 }
126 
127 void run()
128 {
129     LL n, m, k;
130     while (  cin >> n >> m >> k )
131     {
132 
133         LL Area = fun( n, m, k );
134         LL Area2 = fun( m, n, k );
135         if ( Area2 > Area ) Area = Area2;
136         cout << Area << endl;
137 
138     }
139 
140 }
141 
142 
143 int main( int argc, char **argv )
144 {
145 
146 #ifndef ONLINE_JUDGE
147         freopen("in.txt", "r", stdin);
148 //      freopen("out.txt", "w", stdout);
149 #endif
150 
151         time_t st = clock();
152 
153         run();
154 
155         Log("\n=============\n");
156         Log("Time: %.2lf sec\n", (clock() - st) / double(CLOCKS_PER_SEC));
157 
158         return 0;
159 
160 }

 

CodeForces 449A - Jzzhu and Chocolate

标签:des   style   blog   http   color   io   os   ar   strong   

原文地址:http://www.cnblogs.com/vinceliang/p/3988088.html

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