zoukankan      html  css  js  c++  java
  • TZOJ 2289 Help Bob(状压DP)

    描述

    Bob loves Pizza but is always out of money. One day he reads in the newspapers that his favorite pizza restaurant, Alfredo's Pizza Restaurant, is running a competition: they will donate a big pizza to the first person who will tell them the lowest price per area that can be achieved by buying any of the pizzas at most once. "That task is easy!", thinks Bob, "For each pizza I just calculate the average price and the lowest quotient will be the answer.".

    Unfortunately the problem is a bit more complicated: with some pizzas Alberto gives out discount coupons for getting another pizza cheaper and even worse, those coupons can be combined. The pizzas have to be bought one after the other, and it is not possible to use a coupon to get a discount retrospectively for a pizza which has already been bought. Can you help Bob to become the first to solve this task and to get a pizza for free?

    输入

    The input file contains several test cases. Each test case starts with a number m, the number of pizzas Alfredo offers. Input is terminated by m = 0. Otherwise, 1 ≤ m ≤ 15. Then follow m lines describing the pizzas. Each of those following lines describes pizza i (1 ≤ im) and starts with 3 integer numbers pi, ai and ni specifying the price of the pizza, its area and the number of discount coupons you get when buying it, 1 ≤ pi ≤ 10000, 1 ≤ ai ≤ 10000 and 0 ≤ ni < m. Then follow ni pairs of integer numbers xi,j and yi,j specifying the index xi,j (1 ≤ xi,jm, xi,ji) of the pizza you get a discount coupon for and the discount in percentage terms yi,j (1 ≤ yi,j ≤ 50) you get when buying pizza xi,j. You may assume that for each i the values xi,j are pairwise distinct.

    输出

    For each test case print one line containing the lowest price per area that can be achieved by buying any of the pizzas at most once. Round this number to 4 places after the decimal point. Note that you can combine an arbitrary number of discount coupons: for a pizza with price 10 and two rabatt coupons for that pizza with a 50 and a 20 on it, you would only have to pay 10 * 0.8 * 0.5 = 4 monetary units.

    样例输入

    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

    题意

    N个披萨,p价格a面积k送的优惠券数,接着k个代表买x披萨打10-y/10折

    每个披萨最多买1个,问怎么买总价格/总面积最大,并输出值

    题解

    状压DP

    dp[i]代表买了i中二进制为1的披萨花的最少钱

    那么答案就是min(dp[i]/状态i中二进制为1的披萨总面积)

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int N=(1<<15);
     5 int main()
     6 {
     7     int n,p[15],a[15],k[15],x[15][15];
     8     double dp[N],y[15][15];
     9     while(scanf("%d",&n)!=EOF,n)
    10     {
    11         for(int i=0;i<1<<n;i++)dp[i]=1e18;
    12         for(int i=0;i<n;i++)
    13         {
    14             scanf("%d%d%d",&p[i],&a[i],&k[i]);
    15             for(int j=0;j<k[i];j++)
    16             {
    17                 scanf("%d%lf",&x[i][j],&y[i][j]);
    18                 x[i][j]--;
    19                 y[i][j]=1-y[i][j]/100;
    20             }
    21         }
    22         int state=1<<n;
    23         double minn=1e18;
    24         dp[0]=0;
    25         for(int i=0;i<state;i++)
    26         {
    27             double co[15],area=0;
    28             for(int j=0;j<n;j++)co[j]=1.;
    29             for(int j=0;j<n;j++)
    30                 if(i&(1<<j))
    31                 {
    32                     area+=a[j];
    33                     for(int l=0;l<k[j];l++)
    34                         co[x[j][l]]*=y[j][l];
    35                 }
    36             for(int j=0;j<n;j++)
    37             {
    38                 if(i&(1<<j))continue;
    39                 dp[i|(1<<j)]=min(dp[i|(1<<j)],dp[i]+p[j]*co[j]);
    40                 minn=min(minn,dp[i|(1<<j)]/(area+a[j]));
    41             }
    42         }
    43         printf("%.4f
    ",minn);
    44     }
    45     return 0;
    46 }
  • 相关阅读:
    Leetcode 16.25 LRU缓存 哈希表与双向链表的组合
    Leetcode437 路径总和 III 双递归与前缀和
    leetcode 0404 二叉树检查平衡性 DFS
    Leetcode 1219 黄金矿工 暴力回溯
    Leetcode1218 最长定差子序列 哈希表优化DP
    Leetcode 91 解码方法
    Leetcode 129 求根到叶子节点数字之和 DFS优化
    Leetcode 125 验证回文串 双指针
    Docker安装Mysql记录
    vmware虚拟机---Liunx配置静态IP
  • 原文地址:https://www.cnblogs.com/taozi1115402474/p/10383488.html
Copyright © 2011-2022 走看看