Regionals 2015 >> Asia - Tehran >> 7527 - Funfair【贪心】【dp】


7527 - Funfair



题目链接:7527

题目大意:玩一个闯关游戏,初始为x元,总共有n关,自己选择k关,以及过关顺序。过第i关的时候,赢得概率为pi,赢了之后可获得ai元,输了的话,则输去li * x的钱.问如何选择关以及闯关顺序使得最后的金钱数期望最大。

题目思路:首先,需要将关排序,这样可以保证第i+1关一定在i关之后过,然后进行dp,第i关取或者不取。

排序方式: 我们可以知道,过第i关的时候

赢: (Ai + x) * Pi
输: (1 - Pi)(1 - Li) * x

相加合并一下得到(1 - Li + LiPi) * x + Ai * Pi
假设 c = (1 - Li + LiPi)
    d = Ai * Pi
即: cx + d
那么,在考虑先过A关还是B关的时候,有两种可能性,
先过A关:c2 * (c1*x+d1) + d2;
先过B关:c1 * (c2*x+d2) + d1;
假设A大于B,c2 * (c1*x+d1) + d2 > c1 * (c2*x+d2) + d1
化简得到,d1/(c1-1) < d2/(c2-1)

所以:按照 d1/(c1-1) < d2/(c2-1) 方式排序即可。

注意:

1.排序的时候需要考虑c等于1的情况(分母不能为0)

2.p,l代进去算的时候要除以100(因为他们是百分比)

最后dp处理一下就可以了!

以下是代码:

#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <functional>
#include <numeric>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <queue>
#include <deque>
#include <list>

using namespace std;
#define eps 1e-6
struct node
{
    double a,l,p,c,d,s;
}g[105];
bool cmp(node a, node b)
{
    if (a.c == 1 || b.c == 1) return a.c < b.c;  //比较坑!
    return a.s > b.s;
}
double dp[105][105];
int main()
{
    int n,k,x;
    while(cin >> n >> k >> x)
    {
        if (n == 0 && k == 0 && x == 0) break;
        memset(dp,0,sizeof(dp));
        memset(g,0,sizeof(g));
        for (int i = 0; i < n; i++)
        {
            cin >> g[i].a >> g[i].l >> g[i].p;
            g[i].l /= 100;
            g[i].p /= 100;
            g[i].c = 1 - g[i].l + g[i].l * g[i].p;
            g[i].d = g[i].a * g[i].p;
            g[i].s = g[i].d / (g[i].c - 1);
        }
        sort(g,g + n,cmp);
        for (int i = 0; i < n; i++) dp[i][0] = x;

        for (int i = 0; i < n; i++)  //第i个活动选不选
        {
            dp[i][1] = max(x * g[i].c + g[i].d,dp[i][1]);
            for (int l = 0; l < i; l++) //在前l个活动中
            {
                for (int j = 2; j <= min(l+2,k); j++)  //选了j个
                {
                    dp[i][j] = max(dp[i][j],dp[l][j - 1] * g[i].c + g[i].d);

                }
            }
        }
        double ans = 0;
        for (int i = 0; i < n; i++) ans = max(dp[i][k],ans);
        printf("%.2f\n",ans);
    }
}

附上几组测试数据:

/*输入*/
5 3 100
46 15 13
42 36 7
61 71 37
79 89 57
18 99 18

10 5 1000
30 63 64
71 41 41
45 14 27
69 98 91
64 58 23
45 98 93
60 14 87
73 87 82
27 88 75
46 12 32

20 1 10
22 94 19
10 23 91
53 53 73
26 47 96
48 64 54
73 70 96
61 59 58
28 49 63
36 4 35
27 91 52
35 87 32
88 67 58
62 59 60
17 55 58
72 4 52
37 89 26
70 17 33
89 33 10
71 93 61
28 7 88

20 5 10
29 85 12
54 8 14
84 71 16
82 15 3
59 22 71
76 4 33
67 2 97
82 96 52
87 22 25
30 47 30
75 13 25
47 14 80
39 11 75
28 26 94
28 27 34
89 80 3
58 60 32
23 88 32
45 86 56
14 0 63

/*输出*/

90.67
860.39
79.80
213.04
时间: 2024-08-09 21:08:01

Regionals 2015 >> Asia - Tehran >> 7527 - Funfair【贪心】【dp】的相关文章

Regionals 2015 &gt;&gt; Asia - Tehran &gt;&gt; 7530 - Cafebazaar【二分图最佳匹配】【KM】【最大费用流】

Regionals 2015 >> Asia - Tehran >> 7530 - Cafebazaar 题目链接:7530 题目大意:一个公司有n个开发者,有m个APP可开发.其中一些开发者必选,一些APP必选.已知每个开发者开发每个APP的收益,求最大收益.(每个开发者最多开发一个APP,每个APP最多一个人开发) 题目思路: 解法一:二分图最佳匹配(KM算法) 增加一些虚开发者和虚app,非必要app可以被虚开发者开发,收益为0,反过来非必要开发者可以开发虚app,收益为0.

Regionals 2013 Asia - Daejeon (部分题目题解)

题目链接:Regionals 2013 Asia - Daejeon 6500 Boxes 题意:将箱子(矩阵的1)全移动到矩阵的底部需要几步 思路:按列从下到上统计.(n,m)的矩阵,移动一个箱子(x,y),如果有c个箱子在底部,那么移动该箱子的步数是(n-x-c-1). AC代码: #include <stdio.h> #include <string.h> int mp[110][110]; int main() { int t; int i,j,n,m; scanf(&qu

URAL 1203 Scientific Conference(贪心 || DP)

Scientific Conference 之前一直在刷计算几何,邀请赛连计算几何的毛都买见着,暑假这一段时间就做多校,补多校的题目,刷一下一直薄弱的DP.多校如果有计算几何一定要干掉-.- 题意:给你N个报告会的开始时间跟结束时间,问你做多可以听几场报告会.要求报告会之间至少间隔为1. 思路:其实是个活动安排问题,可以用贪心也可以用DP,贪心写起来会比较简单一些,因为练习DP,所以又用DP写了一遍. 贪心的话就是一个很简单的活动选择问题,从结束时间入手,找每次的最优选择. 1 struct n

codeforces349B - Color the Fence 贪心+DP

题意:1-9每个字母需要消耗ai升油漆,问你用油漆最多刻意画多大的数字 解题思路: 首先我们要贪心,可以知道我最优是先使我们位数尽可能长,然后才是就是位数长的情况下使得从最高位开始尽可能大.所以要取满足最长位最小的那个数,方便我们DP 解题代码: 1 // File Name: 349b.cpp 2 // Author: darkdream 3 // Created Time: 2014年07月24日 星期四 21时40分13秒 4 5 #include<vector> 6 #include&

HDU 4939 Stupid Tower Defense(贪心+dp)

HDU Stupid Tower Defense 题目链接 题意:有一些塔,红塔能攻击经过他的,绿塔能攻击经过之后的,蓝塔能把经过之后的减速,求在1-n上放塔,求伤害最大值 思路:一开始以为直接贪心,绿塔最前,蓝塔中间,红塔最后就可以了,结果其实是错的 不过,红塔放最后是肯定的,这个很显然就不多证明了,是贪心的思想 然后就dp[i][j]表示放到i,前面有j个绿塔去状态转移即可 代码: #include <cstdio> #include <cstring> #include &l

CF459E Pashmak and Graph【贪心+dp】

题目:CF459E Pashmak and Graph 题意:给出n个点,m条边的图,然后让你每次只能向权值更大边走,求最大的边数.可以走多次 分析:由于点比较多,我们可以先对权值从小到大排序,然后从小的开始,更新它的到的节点的值为前一个节点值+1,但是还会出现权值相等成环的情况,所以我们可以对相等的先不更新,保存起来,等相等的结束了再更新. 代码: #include<cstdio> #include<algorithm> using namespace std; const in

贪心+dp

贪心+dp 好多题都是这个思想, 可以说是非常重要了 思想一: 在不确定序列无法dp的情况下, 我们不妨先假设序列已经选定, 而利用贪心使序列达到最优解, 从而先进行贪心排序, 在进行dp选出序列 思想二: 最优解一定满足上一个状态在某 Problem 1 n 座楼房,立于城中. 第 i 座楼,高度 \(h_i\) . 你需要一开始选择一座楼,开始跳楼.在第 座楼准备跳楼需要 的花费.每次可以跳到任何一个还没有跳过的楼上去.但跳楼是有代价的,每次跳到另外一座楼的代价是两座楼高度的差的绝对值,最后

poj 3016 K-Monotonic 左偏树 + 贪心 + dp

//poj 3016 K-Monotonic//分析:与2005年集训队论文黄源河提到的题目类似,给定序列a,求一序列b,b不减,且sigma(abs(ai-bi))最小.//思路:去除左偏树(大根堆)一半的节点(向上取整),让左偏树的根节点上存放中位数:每个左偏树的根节点表示一个等值区间//在本题中,我们将一段区间 与 一颗左偏树等同:将求调整给定数列 vi 为不减序列的代价 与 求取数列 bi 等同 1 #include"iostream" 2 #include"cstd

ZOJ 3689 Digging(贪心+dp)

Digging Time Limit: 2 Seconds      Memory Limit: 65536 KB When it comes to the Maya Civilization, we can quickly remind of a term called the end of the world. It's not difficult to understand why we choose to believe the prophecy (or we just assume i