hdu 1864

来源:互联网 发布:linux man命令 下一页 编辑:程序博客网 时间:2024/05/24 06:39

题目概述

给定报销额上限Q,可报销同时满足下述条件的发票:
不含A,B,C类以外的物品,单类物品总价不超过600,整张发票总价不超过1000
发票不可拆分报销,任意条件不满足则整张发票不可报销,给定N张发票,求最多报销多少钱

时限

1000ms/1000ms

输入

每组数据第一行一个正浮点数Q和一个正整数N,其后N行,每行第一个正整数i,其后i个项目,每个项目格式为type:cost,type为一大写英文字符,代表物品类别,cost为一正浮点数,代表价格,两个项目之间有一个空格,输入到N=0为止

限制

1<=N<=30;所有浮点数至多精确到小数点后2位

输出

每行一个浮点数,最大报销额,精确到小数点后2位

样例输入

200.00 3
2 A:23.50 B:100.00
1 C:650.00
3 A:59.99 A:120.00 X:10.00
1200.00 2
2 B:600.00 A:400.00
1 C:200.50
1200.50 3
2 B:600.00 A:400.00
1 C:200.50
1 A:100.00
100.00 0

样例输出

123.50
1000.00
1200.50

讨论

dp,题本身不难,但原题没说清楚一些限制条件,而且这个输入格式也非常烦人,其实莫过于一个带上限的求最大子序列和,加个if就够,最多30张票,n^2也不担心超时,转移方程已经在代码中标注
看到讨论版有把这个题当背包做的,万幸浮点数小数位数有限,数据也比较水,额也尝试了一下,249MS,13456K,还是算了吧

题解状态

0MS,1720K,1145 B,C++

题解代码

#include<algorithm>#include<cstring>#include<cstdio>using namespace std;#define INF 0x3f3f3f3f#define maxx(a,b) ((a)>(b)?(a):(b))#define minn(a,b) ((a)<(b)?(a):(b))#define MAXN 32#define memset0(a) memset(a,0,sizeof(a))int N;//发票数double Q, piao[MAXN], dp[MAXN];//报销额上限 发票原始数据 dp辅助数组double fun(){    for (int p = 0; p < N; p++) {        int i;//单张票的项目数 i临时变量的名称之一        scanf("%d", &i);        double A = 0, B = 0, C = 0;//有效的三类物品总价        bool f = 0;//出现其他种类物品时变成true 发票作废        while (i--) {            char type;//种类            double cost;//价格            scanf(" %c:%lf", &type, &cost);            if (type == 'A')//不用switch只是因为懒得打break;                A += cost;            else if (type == 'B')                B += cost;            else if (type == 'C')                C += cost;            else                f = 1;//出现其他类别 发票作废        }        piao[p] = A + B + C;        if (f || piao[p] > 1000.0 || A > 600.0 || B > 600.0 || C > 600.0)//种类错或发票总价超限或三类物品总价超限            piao[p] = 0.0;//一分钱也不报销    }    for (int p = 0; p < N; p++)//不需要额外排序        for (int i = p; i >= 0; i--)//倒序以先用自身票值初始化dp值            if (dp[i] + piao[p] <= Q)//不能超出钱上限                dp[p] = maxx(dp[p], dp[i] + piao[p]);//重要的转移方程重要的转移方程重要的转移方程    return *max_element(dp, dp + N);//dp数组的末元素未必最大 需要额外找出最大值}int main(void){    //freopen("vs_cin.txt", "r", stdin);    //freopen("vs_cout.txt", "w", stdout);    while (~scanf("%lf%d", &Q, &N) && N) {//input        printf("%.2lf\n", fun());//input        memset0(dp);//原始数据数组会被新数据覆盖 无需清零    }}

EOF

0 0
原创粉丝点击