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

P4160 [SCOI2009]生日快乐[dfs]

时间:2019-10-22 20:03:51      阅读:68      评论:0      收藏:0      [点我收藏+]

标签:个人   iostream   getch   题目   最大值   mod   ble   一个   fine   

题目描述

windy的生日到了,为了庆祝生日,他的朋友们帮他买了一个边长分别为 X 和 Y 的矩形蛋糕。

现在包括windy,一共有 N 个人来分这块大蛋糕,要求每个人必须获得相同面积的蛋糕。

windy主刀,每一切只能平行于一块蛋糕的一边(任意一边),并且必须把这块蛋糕切成两块。

这样,要切成 N 块蛋糕,windy必须切 N-1 次。

为了使得每块蛋糕看起来漂亮,我们要求 N 块蛋糕的长边与短边的比值的最大值最小。

你能帮助windy求出这个比值么?

解析

这题使我深刻领悟到我有多菜。

结论:切的位置的坐标一定是\(X/N\)\(Y/N\)的整数倍。

证明:用反证法。若某一刀切出的短边比\(X/N\)小,那么一定需要一个比\(Y\)还长的长边才能满足题目要求,显然不能切。

若某一刀切得比\(X/N\)大,比如切出来一个\(X/N+k,k<X/N\),那么切出来的这块矩形的长边一定小于\(Y\)且大于\(Y*(N-1)/N\),这样就会余出来一段\(p\),且\(0<p<Y/N\)。然而为了满足题目条件,我们势必要使\(p\)构成的矩形面积也等于\(X*Y/N\),但是它最大也就是\(p*X\),显然\(p*X<X*Y/N\),这是不可能的。

证毕。

明白这一点之后这题就简单了,但是我是个连深搜都写不对的菜鸡。

显然切一刀会分成两个子问题,而每次我们可以在所有合法位置横纵切。选择子问题所有情况中最大值最小的情况进行回溯即可。

参考代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 101
#define MOD 2520
#define E 1e-12
using namespace std;
inline int read()
{
    int f=1,x=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
double n;
double x,y,kx,ky;
inline double dfs(double k,double nx,double ny)
{
    if(k==1){
        if(nx<ny) swap(nx,ny);
        return nx/ny;
    }
    double ans=INF,t1,t2;
    double kx=nx/k,ky=ny/k;
    for(int i=1;i<=k/2;++i){
        t1=max(dfs(k-i,nx-i*kx,ny),dfs(i,i*kx,ny));
        t2=max(dfs(k-i,nx,ny-i*ky),dfs(i,nx,i*ky));
        ans=min(ans,min(t1,t2));
    }
    return ans;
}
int main()
{
    cin>>x>>y>>n;
    printf("%.6lf",dfs(n,x,y));
    return 0;
}

P4160 [SCOI2009]生日快乐[dfs]

标签:个人   iostream   getch   题目   最大值   mod   ble   一个   fine   

原文地址:https://www.cnblogs.com/DarkValkyrie/p/11722097.html

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