zoukankan      html  css  js  c++  java
  • 天上掉Pizza

    天上掉Pizza

    时间限制: 3 Sec  内存限制: 128 MB
    提交: 73  解决: 48
    [提交][状态][讨论版]

    题目描述

    明明喜欢Pizza,但总是缺钱。有一天,他在报纸上阅读,他最喜爱的比萨饼店��必胜客,正在对大批新Pizza运行的促销。促销的办法是:在购买一些Pizza后,可能得到一些优惠券,可以对另一些Pizza进行打折,更令人惊喜的是这些优惠券可以结合起来。但是,有一个限制,Pizza必须一个接一个买,而后得到的优惠券也不可能追溯前面已经买过的Pizza。明明想尝试若干新品Pizza,可又没有充足的钱,为了能省一些,明明费劲脑力,就请你帮他计算一下如何购买Pizza,使得其平均价格最低!平均价格是指买到Pizza的总价格/总面积,即单位面积的Pizza的价格。还要注意,“安排顺序”只要求按照给定的顺序安排每个操作。不一定是各机器上的实际操作顺序。在具体实施时,有可能排在后面的某个操作比前面的某个操作先完成。
     

    输入

    有多组输入数据。 
    每组输入数据第一行为m(1<=m<=15). 
    接下来m行,每行前3个数pi,ai,ni(1<=pi<=10000,1<=ai<=10000,0<=nipi为编号为i的Pizza的价格,ai为编号为i的Pizza的面积,ni为购买i号Pizza能得到ni张优惠券 
    接下来ni*2个数,分别表示该张优惠券对xi号Pizza打折(1<=xj<=m,i<>xj),折扣为yj(1<=yj<=50) 
    输入以m=0结束。 

    输出

    输出购买m个Pizza中某一些的最低单位面积价格。保留4位小数。 
    (如果一个Pizza原价10,得到了一张50和一张20的优惠券,那么购买它实际所需的价值就是10*0.5*0.8=4) 

    样例输入

    1
    80 30 0
    2
    200 100 1 2 50
    200 100 0
    5
    100 100 2 3 50 2 50
    100 100 1 4 50
    100 100 1 2 40
    600 600 1 5 10
    1000 10 1 1 50
    0

    样例输出

    2.6667
    1.5000
    0.5333
    

    提示

    Pizza可以不全部购买

    一眼看下去也许没什么思路,阅读量有些大,还好输出那里有些提示,看m的范围,也就是披萨总数可以发现,可以将披萨压缩,

    表示为已经买了哪几个披萨,因此dp[x]表示买了x状态的披萨的最小那个什么。。

    和导游2还是有些类似的,但这里需要预处理出买了第几个披萨对其他披萨的优惠,这样一个数组,然后和导游2的转移差不多类似。

    #include<cstdio> 
    #include<algorithm> 
    #include<cmath> 
    #include<iostream> 
    #include<cstring> 
    #include<string> 
      
    using namespace std; 
    const int MAXN=17; 
    struct fzy 
    { 
        double s,fee,ave; 
        void init() 
        { 
            s=fee=ave=-1; 
        } 
    }dp[(1<<16)+1]; 
      
    double g[MAXN][MAXN]; 
    int a[MAXN],p[MAXN]; 
    int n,num; 
      
    void init() 
    { 
        for (int i=0;i<MAXN;i++) 
            for (int j=0;j<MAXN;j++) 
                g[i][j]=1; 
        for (int i=0;i<=(1<<16);i++) 
            dp[i].init(); 
    } 
    void dfs(int sta,int num) 
    { 
        if (num==0) 
        { 
            dp[sta].s=0; 
            dp[sta].fee=0; 
            dp[sta].ave=0; 
            return; 
        } 
        if (dp[sta].fee>0) return; 
          
        double rs,rf,ra=1<<MAXN; 
        int xx; 
          
        for (int i=0;i<n;i++) 
        { 
            if ((1<<i)&sta) 
            { 
                xx=sta^(1<<i); 
                dfs(xx,num-1); 
                double x=p[i+1]*1.0; 
                for (int ii=0;ii<n;ii++) 
                    if ((1<<ii)&xx) 
                    { 
                        x*=g[ii+1][i+1]; 
                    } 
                x+=dp[xx].fee; 
                if (x<ra) ra=x; 
            } 
        } 
        dp[sta].fee=ra; 
    } 
    double min(double a,double b) 
    { 
        return a>b?b:a; 
    } 
    int main() 
    { 
        while (scanf("%d",&n)&&n) 
        { 
            init(); 
                  
            int num,x,y; 
            for (int i=1;i<=n;i++) 
            { 
                      
                scanf("%d%d%d",&p[i],&a[i],&num); 
                for (int j=1;j<=num;j++) 
                { 
                    scanf("%d%d",&x,&y); 
                    g[i][x]=(1-y*1.0/100); 
                } 
            } 
              
            dfs((1<<n)-1,n); 
              
            double ans=1<<MAXN; 
            for (int i=1;i<=(1<<n);i++) 
            { 
                dp[i].s=0; 
                for (int j=0;j<n;j++) 
                    if (i&(1<<j)) dp[i].s+=a[j+1]; 
                dp[i].ave=dp[i].fee/dp[i].s; 
            } 
            for (int i=1;i<(1<<n);i++) 
                ans=min(ans,dp[i].ave); 
            printf("%.4f
    ",ans);    
        } 
    } 
  • 相关阅读:
    查询存储过程 视图调用关系
    正在执行的sql
    [BAT] BAT 顺序执行其他BAT 批处理文件可设置时间间隔(实际场景Windows下依次启动多个Tomcat服务)
    QT 实用代码片段 (持续更新)
    C# 阻塞队列 BlockingQueue<T>
    [Windows] IE版本历史
    [Windows] Windows操作系统的历史
    [C#] 使用表驱动法替代IF Else 和 Switch Case
    Bat实现IP设置切换(公司IP和家里的IP)
    Sublime Text 2 常用快捷键
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/6894611.html
Copyright © 2011-2022 走看看