[SCOI2009]生日快乐

嘟嘟嘟

这道题最多只切9刀,然后爆搜就过了(这只是感性理解吧,复杂度我不太会算)。

怎么爆搜呢,首先,如果一个长为x,宽为y的蛋糕被分成k份,那么每一份长最小为x / k,宽最小为y / k,而且每一块蛋糕的长和宽都是这个数的整数倍,这个不难理解。

然后就可以爆搜了:对于每一个状态(x, y, k)枚举他被横着切的情况和纵着切的情况,也就是总共2 * k种,那横着切举例,分别比较切开的两种状态的比值,这么递归下去直到k == 1,此时返回max(x, y) / min(x, y)即可,然后取最大的,再在这些最大的中取最小的就是答案。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<cctype>
 8 #include<vector>
 9 #include<stack>
10 #include<queue>
11 using namespace std;
12 #define enter printf("
")
13 #define space printf(" ")
14 #define Mem(a) memset(a, 0, sizeof(a))
15 typedef long long ll;
16 typedef double db;
17 const int INF = 0x3f3f3f3f;
18 const int eps = 1e-8;
19 //const int maxn = ;
20 inline ll read()
21 {
22     ll ans = 0;
23     char ch = getchar(), last = ' ';
24     while(!isdigit(ch)) {last = ch; ch = getchar();}
25     while(isdigit(ch))
26     {
27         ans = ans * 10 + ch - '0'; ch = getchar();
28     }
29     if(last == '-') ans = -ans;
30     return ans;
31 }
32 inline void write(ll x)
33 {
34     if(x < 0) x = -x, putchar('-');
35     if(x >= 10) write(x / 10);
36     putchar(x % 10 + '0');
37 }
38 
39 int x, y, n;
40 db dfs(db x, db y, int k)
41 {
42     if(k == 1) {return max(x, y) / min(x, y);}
43     db ans = (db)INF * (db)INF, tx = x / (db)k, ty = y / (db)k;
44     for(int i = 1; i <= (k >> 1); ++i)
45     {
46         db t1 = max(dfs(tx * i, y, i), dfs(x - tx * i, y, k - i));    //横向切 
47         db t2 = max(dfs(x, ty * i, i), dfs(x, y - ty * i, k - i));    //纵向切 
48         ans = min(ans, min(t1, t2));
49     }
50     return ans;
51 }
52 
53 int main()
54 {
55     x = read(); y = read(); n = read();
56     printf("%.6lf
", dfs(x, y, n));
57     return 0;
58 }
View Code
原文地址:https://www.cnblogs.com/mrclr/p/9488121.html