武大校赛-Your NP has been charged full

                      Your NP has been charged full(题目链接


题目大意:
给你一个数N,表示有N回合,然后跟3*N个数
表示每回合有3个buff,ai,bi,ci,这些buff可以提高伤害,并且可以持续3回合,伤害计算为
(1+∑ai)*(1+∑bi)*(1+∑ci)
求最高伤害

动规题目,我刚开始的思路就是举出所有的情况找出其中的最优解!
这个思路是正确的,但是具体不是那么容易实现,因为一个buff要持续三个回合
那么如何判断这三个回合到了,buff失效了?还有如何记录我上次,还有上上次选择了什么buff
这对于我来说都是难题,但是看了大神代码发现我的问题都不是问题,其实都不用考虑的
判断buff失效?不存在的。记录以前选过的buff?不存在的。
当你选到第i个buff了,你可以现在开始遍历,遍历第i,i-1,i-2个回合的3*3*3的27种情况找出最优解
为什么要开ans是【10005】【9】而不是ans【100005】【3】或者其他
那是因为9是表示第i,第i-1回合的9种情况
那么又是为什么要记录上两回合的情况?
因为我用第三回合的时候要用到上两个回合的情况,因为buff持续3回合,我列举了上两个回合的所有情况,
那么我就可以直接用,来递推出次回合的情况了

#include <bits/stdc++.h>
using namespace std;
double a[10005][3];   //a存的是buff的加成数值,即题目给的数据
double ans[10005][9];//ans存的是计算的总伤害数值
int n;
double calc(int _i, int _a, int _b, int _c)//用来计算选上第i回合选伤害
{
    double _res[3];                        //其中的a,b,c表示上上回合,上回合,以及这回合选择的buff
    memset(_res, 0, sizeof _res);
    _res[0] = _res[1] = _res[2] = 1;
    _res[_a] += a[_i - 2][_a];
    _res[_b] += a[_i - 1][_b];
    _res[_c] += a[_i][_c];
//	printf("%d %d %d %d = %.6lf (%.3lf * %.3lf * %.3lf)\n", _i, _a, _b, _c, _res[_a] * _res[_b] * _res[_c], _res[_1]);
    return _res[0] * _res[1] * _res[2];
}
int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
        for (int j = 0; j < 3; j++)
            cin >> a[i][j];           //将buff存到a数组里面
    for (int i = 0; i < 3; i++)
        ans[1][i] = 1 + a[1][i];    //将第一个初始化,buff都选上存到ans中
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)//前两个buff一共是3*3种情况,全部列出来存到ans中
            if (i != j)
            {
                ans[2][i * 3 + j] = ans[1][i] + (1 + a[1][i]) * (1 + a[2][j]);
            }
            else
            {
                ans[2][i * 3 + j] = ans[1][i] + (1 + a[1][i] + a[2][j]);
            }
    for (int i = 3; i <= n; i++)//从第三个开始又换一种dp方法
    {
        for (int _a = 0; _a < 3; _a++)        //3个回合一循环,比如i回合就要找i-1回合,i-2回合的buff所有情况进行遍历
        {
            for (int _b = 0; _b < 3; _b++)     //a,b,c就是用来遍历这三回合的所有情况
            {
                for (int _c = 0; _c < 3; _c++)
                {
                    ans[i][_b * 3 + _c] = max(ans[i][_b * 3 + _c],ans[i - 1][_a * 3 + _b] + calc(i, _a, _b, _c));
                    //这个dp方程为的就是对于第i-1已经存下的9种最优解找一下分别看一下是否加上第i回合的第c个buff
                }
            }
        }
    }
    double _ans = 0;
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            _ans = max(_ans, ans[n][i * 3 + j]);   //dp完毕,从9种情况下找一下最大值
    printf("%.6f\n", _ans);
    return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值