#P1020. 第1题-切大饼
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 231
            Accepted: 53
            Difficulty: 5
            
          
          
          
                       所属公司 : 
                              科大讯飞
                                
            
                        
              时间 :2022年10月14日
                              
                      
          
 
- 
                        算法标签>递归          
 
第1题-切大饼
题目思路
首先我们假设当前的矩形长为 x,宽为 y,要分出 k 块,那么不难想到分出的一块的长 dx 最短为x/k,宽 dy 最短为 y/k,而且每次切的长度一定是 dx 的倍数或 dy 的倍数,于是我们递归搜索能切的每个比例,每次切长或者宽,在分出的两块中取比值的最大值,更新最大值的最小值,返回即可。
代码
Python代码
def dfs(x, y, n):
	x, y = max(x, y), min(x, y)		#规定x为长,y为宽
	if n == 1:	#如果当前只是切成一块,则返回长宽比
		return x/y
	dx, dy = x/n, y/n		#所能切的最小单位
	ans = 1e9		#返回值
	for i in range(1, n//2+1):		#切长有n/2中决策,切成(dx,(n-1)dx)、(2dx,(n-2)dx) ....,切宽一样
        #切下dx*i,y 的矩形,剩余部分为 x-dx*i, y,面积比是i:n-i,所以dfs(dx*i, y, i)是第一块的最后结果,
        #dfs(x-dx*i, y, n-i)是第二块的,二者取max得到最大值,最小化最大值,所以和ans取min
		ans = min(ans, max(dfs(dx*i, y, i), dfs(x-dx*i, y, n-i)))
        #切宽同理
		ans = min(ans, max(dfs(x, dy*i, i), dfs(x, y-dy*i, n-i)))
	return ans
x, y, n = map(int, input().split())
print("%.6lf"%dfs(x,y,n))	#直接输出即可
C++代码
#include <iostream>
using namespace std;
double dfs(double x, double y, int n)
{
    double a = min(x, y);
    double b = max(x, y);
    x = b, y = a;	//规定x为长,y为宽
    if (n == 1)	//如果当前只是切成一块,则返回长宽比
        return x / y;	
    double dx = x / n, dy = y / n;	//所能切的最小单位
    double ans = 1e9;
    for (int i = 1; i <= n / 2; i++) {	//切长有n/2中决策,切成(dx,(n-1)dx)、(2dx,(n-2)dx) ....,切宽一样
        //切下dx*i,y 的矩形,剩余部分为 x-dx*i, y,面积比是i:n-i,所以dfs(dx*i, y, i)是第一块的最后结果,
        //dfs(x-dx*i, y, n-i)是第二块的,二者取max得到最大值,最小化最大值,所以和ans取min
        ans = min(ans, max(dfs(dx * i, y, i), dfs(x - dx * i, y, n - i)));
        ans = min(ans, max(dfs(x, dy * i, i), dfs(x, y - dy * i, n - i)));//切宽同理
    }
    return ans;
}
int main()
{
    double x,y;
    int n;
    cin>>x>>y>>n;
    printf("%.6lf\n", dfs(x,y,n));
    return 0;
}
Java代码
import java.util.Scanner;
class Main {
    public static double dfs(double x, double y, int n) {
        double a = Math.min(x, y);
        double b = Math.max(x, y);
        x = b;	//规定x为长,y为宽
        y = a;
        if (n == 1)	//如果当前只是切成一块,则返回长宽比
            return x / y;
        double dx = x / n, dy = y / n;	//所能切的最小单位
        double ans = 1e9;
        for (int i = 1; i <= n / 2; i++) {	//切长有n/2中决策,切成(dx,(n-1)dx)、(2dx,(n-2)dx) ....,切宽一样
            //切下dx*i,y 的矩形,剩余部分为 x-dx*i, y,面积比是i:n-i,所以dfs(dx*i, y, i)是第一块的最后结果,
        	//dfs(x-dx*i, y, n-i)是第二块的,二者取max得到最大值,最小化最大值,所以和ans取min
            ans = Math.min(ans, Math.max(dfs(dx * i, y, i), dfs(x - dx * i, y, n - i)));
            ans = Math.min(ans, Math.max(dfs(x, dy * i, i), dfs(x, y - dy * i, n - i)));//切宽同理
        }
        return ans;
    }
    public static void main(String[] args) {
        double x, y;
        int n;
        Scanner scanner = new Scanner(System.in);
        x = scanner.nextDouble();
        y = scanner.nextDouble();
        n = scanner.nextInt();
        System.out.printf("%.6f", dfs(x, y, n));
    }
}
Js代码
process.stdin.resume();
process.stdin.setEncoding('utf-8');
let input = '';
process.stdin.on('data', (data) => {
	input += data;
	return;
});
process.stdin.on('end', () => {
    function roundFun(value, n) {	//保留n位小数的函数
      return Math.round(value*Math.pow(10,n))/Math.pow(10,n);
    }
    function dfs(x,y,n)
    {
        let a = Math.min(x, y);
        let b = Math.max(x, y);
        x = b, y = a;	//规定x为长,y为宽
        if (n == 1)	//如果当前只是切成一块,则返回长宽比
            return x / y;
        let dx = x / n, dy = y / n;	//所能切的最小单位
        let ans = 1e9;
        for (let i = 1; i <= parseInt(n / 2); i++) {	//切长有n/2中决策,切成(dx,(n-1)dx)、(2dx,(n-2)dx) ....,切宽一样
            //切下dx*i,y 的矩形,剩余部分为 x-dx*i, y,面积比是i:n-i,所以dfs(dx*i, y, i)是第一块的最后结果,
        	//dfs(x-dx*i, y, n-i)是第二块的,二者取max得到最大值,最小化最大值,所以和ans取min
             ans = Math.min(ans, Math.max(dfs(dx * i, y, i), dfs(x - dx * i, y, n - i)));
             ans = Math.min(ans, Math.max(dfs(x, dy * i, i), dfs(x, y - dy * i, n - i)));//切宽同理
        }
        return ans;
    }
    input=input.split('\n');
    let x=Number(input[0].split(' ')[0]);
    let y=Number(input[0].split(' ')[1]);
    let n=Number(input[0].split(' ')[2]);
    console.log(roundFun(dfs(x,y,n),6));
})
        题目内容
小红买了一个长为 a ,宽为 b的大饼,一共有 n 个人来一起吃这张大饼,要求每个人必须获得相同面积的大饼。现在小红被要求每一切只能平行于一块大饼的一边(任意一边),并且必须把这块大饼切成两块。那么我们要切成 n 块饼的话,小红必须切 n−1 次。
小红患有重度强迫症,他一定要求 n 块大饼的长边与短边的比值的最大值最小。你能帮小红计算出这个比值吗
输入描述
一行三个整数 a , b , n , 分别表示大饼的长,宽以及人数
输出描述
一个浮点数,保留 6 位小数,表示切分后大饼的长边与短边的比值
样例
输入:
1 2 3
输出:
1.500000