URAL 1755 Cake

来源:互联网 发布:医疗数据采集 编辑:程序博客网 时间:2024/06/05 17:36

    链接:http://vjudge.net/problem/viewProblem.action?id=24604

    题解:这道题说清楚挺麻烦的,我就盗用一下中山大学 LiYuzhu 同学的题解吧,版权所属,不要来找我。代码一份是他的,一份是我的。


题目大意:
    Karlsson和 LittleBoy想要分割一块含有 n克奶油和 m克巧克力的蛋糕,由 LittleBoy切割,Karlsson先选。每个人对蛋糕的估值函数不同,Little Boy的为 a1x + b1y,Karl的为 a2x + b2y。现给出四个系数和 n,m,求一种能使 LittleBoy收益最大的切割方式。其中,Little Boy可以在不超过 n和 m的范围下,切割出含有任意克奶油和巧克力的蛋糕。而当两块蛋糕对 Karlsson来说估值相同时,Karlsson会让出对 Little Boy 来说估值较高的那一块。


思路:
    首先,想要使 Little Boy的收益最高,约束就是使得两块蛋糕对 Karl来说估值一样。


    设两块蛋糕中任意一块有 x克奶油和 y克巧克力,则应有

              a2x + b2y = a2(n - x) + b2(m - y)


    可以用反证法证明,假设 a2x + b2y < a2(n - x) + b2(m - y),那么 Karl会选择 n–x克奶油和 m–y克巧克力的蛋糕,而 LittleBoy会得到 x克奶油和 y克巧克力的蛋糕。

    但是必定存在 x+Δx和 y+Δy,使得

             a2(x + Δx) + b2(y + Δy) = a2(n – x -Δx) + b2(m – y - Δy)成立,

    而这时对 LittleBoy来说,显然 x+Δx克奶油和 y+Δy克巧克力的蛋糕相比原来的蛋糕收益更高。

             a2x + b2y > a2 (n - x) + b 2(m - y) 的情况同理可证。


    答案只要求输出符合题意的任意一种分割方法中的任意一块的含奶油和巧克力量,不妨设 LittleBoy得到的是(x,y)的那一块。

    题目要求让 LittleBoy的估值函数 V = a1 x + b1 y 最大。从 a2x + b2y = a2(n - x) + b2(m - y)可以得到 y和 x的关系式,代入函数 V中,可得到 V和 x的关系式,为一次函数 V(x) = kx + b。

    接下来只要根据 k的正负,来确定使得 V(x)最大的 x的值,在通过上面的约束条件算出 y即可,注意需确保 x和 y在取值范围内。

    如果 k < 0,则确保 x越小越好,因此直接取 x = 0,算出 y,判断 y是否在 0 ~ m 范围内,如果不在,则令 y = m,反算出 x 即可。

    如果 k > 0,则确保 x越大越好,因此直接取 x = n,算出 y,判断 y是否在 0 ~ m 范围内,如果不在,则令 y = 0,反算出 x 即可。

    如果 k = 0 的,代表可以随意确定 x,那么随便套用上面一种情况即可。


    有几种特殊情况:

    通过计算可知 k = a 1 – a2 * b1 / b 2,而且在确保 x和 y在取值范围内时 a 2 也会出现在分母,因此对于 a 2 和 b 2 等于 0的情况特殊对待。

     a2 =b2 =0,则 x = n,y = m,即 LittleBoy拿走全部

     a2 = 0, b2 ! = 0 ,则 x = n,y = m / 2,即 LittleBoy拿走全部奶油,而巧克力对半分即可

     a2 ! =0 ,b 2 =0 , 则 x = n / 2,y = m,即 LittleBoy拿走全部巧克力,而奶油对半分即可


LiYuzhu 同学的代码:

#include<iostream>#include<iomanip>using std::cin;using std::cout;using std::endl;int main(void){    double a1,b1,a2,b2;    double n,m;    double x,y;    cin>>a1>>b1>>a2>>b2;    cin>>n>>m;    //步骤 1    if(a2==0 && b2==0)    {        x=n;        y=m;    }    else if(a2==0&&b2!=0)    {        x=n;        y=m/2;    }    else if(a2!=0&&b2==0)    {        x=n/2;        y=m;    }    //步骤 2,y和 x的关系式均由约束方程化简得到    else if((a1-a2 *b1/b2)<0.0)    {        x=0;        y=(n*a2/b2+m)/2;        if(y>m)        {            y=m;            x=(n-m*b2/a2)/2;        }    }    else if((a1-a2 *b1/b2)>0.0)    {        x=n;        y=((n-2*x)*a2/b2+m)/2;        if(y<0)        {        y=0;        x=(n+m*b2/a2)/2;        }    }    else    {        x=0;        y=(n*a2/b2+m)/2;        if(y>m)        {            y=m;            x=(n-m*b2/a2)/2;        }    }    //步骤 3    cout<<std::setiosflags(std::ios::fixed)<< std::setprecision(8)<<x<<" "<<y<<endl;    return 0;}

我的:

#include <iostream>#include <cstring>#include <string>#include <iomanip>using namespace std;int main(){double a1,b1,a2,b2;double x,y;cin>>a1>>b1>>a2>>b2;cin>>x>>y;double h = (a2*x + b2*y)/2.0;double y1 = h/(b2*1.0);double x2 = (h - b2*y)/(a2*1.0);double x3 = h/(a2*1.0);double y4 = (h - a2*x)/(b2*1.0);double ness = 0;double ansx,ansy;if(y1 >= 0 && y1 <= y){if(b1*y1 > ness){ansx = 0,ansy = y1;}}else if(x2 >= 0 && x2 <= x){if(a1*x2 + b1*y > ness){ansx = x2,ansy = y;}}else if(x3 >= 0 && x3 <= x){if(a1*x3 > ness){ansx = x3,ansy = 0;}}else if(y4 >= 0 && y4 <= y){if(a1*x + b1*y4 > ness){ansx = x,ansy = y4;}}cout<<fixed<<setprecision(8)<<ansx<<' '<<fixed<<setprecision(8)<<ansy<<endl;return 0;}

0 0
原创粉丝点击