2018-2019 ACM-ICPC, Asia East Continent Finals I Misunderstood … Missing(level-2)(将未知量作为dp数组的某一维)

I. Misunderstood … Missing

time limit per test

1.0 s

memory limit per test

256 MB

input

standard input

output

standard output

Warm sunshine, cool wind and a fine day, while the girl watching is pursuing in chaos. Rikka reached out her hand and got the garland on her head, finding LCR with the immortal smile. The dream ended up waking, but the doubts will never disappear. In the end, without knowing about LCR, Rikka was invited to Shuyuan Men, a street of Chinese traditional arts in Xi'an.

"Is it enough to use the stored wires?"

"No problem... Those leaders are only concerned about expanding EC Final for the school's and their 'achievements'. All chores are ours. It is fine to simply connect those wiring boards in the series for each row."

Their conversation engaged Rikka. Feeling strange, she decided to follow them. But before all, she needs to beat the devil in her heart.

Rikka has an aggressivity AA and an increment DD of it, which are both 00 initially. There are nn rounds in total. For i=1,2,…,ni=1,2,…,n , at the beginning of ii -th round Rikka's aggressivity AA increases by the increment DD , and then she can do one of the following:

  1. Attack and cause a damage of (A+ai)(A+ai) .
  2. Use the Omnipotent Garland from LCR to increase the increment DD by bibi .
  3. Use her Schwarz Sechs Prototype Mark II to increase the aggressivity AA by cici .

Rikka wonders the maximal possible damage she could cause in total. Could you help her?

Input

The first line contains a single integer T (1≤T≤10)T (1≤T≤10) , the number of test cases. Then TT test cases follow.

The input format of each test case is as follows:

The first line contains a single integer n (1≤n≤100)n (1≤n≤100) , the number of rounds.

The following nn lines contain {ai},{bi},{ci}{ai},{bi},{ci} for i=1,2,…,ni=1,2,…,n . The ii -th line among them contains three integers ai,bi,ci (1≤ai,bi,ci≤109)ai,bi,ci (1≤ai,bi,ci≤109) separated by spaces in order.

It is guaranteed that the sum of nn in all test cases is at most 100100 .

Output

Output TT lines; each line contains one integer, the answer to that test case.

Example

Input

Copy

3
2
3 1 2
3 1 2
3
3 1 2
3 1 2
3 1 2
5
3 1 2
3 1 2
3 1 2
3 1 2
3 1 2

Output

Copy

6
10
24

 

题意:

你现在有攻击力A=0和增长值D=0

每一回合,你的攻击力会增加,A=A+D

然后进行选择,1.发出攻击,伤害为ai+A

2.增加D,D=D+bi

3.增加A,A=A+ci

问你经过n轮之后,最大的伤害值是多少

 

解析:

这道题想了接近一天,但一点都没有思路。

因为这道题对于每一种选择,依据是不同的,选择ai是依据攻击力A(即依据在他之前的回合的选择)

ci,bi是依据下面选择1的回合数(即在他之后的选择),只有这样,才能比较三者的贡献,然后取最大值

我的思路是这样的,但是这个思路是按照类似贪心的思路取选择的,即每遍历到一轮,就想选定他的选择

但是按照动态规划的思路,我们不需要去选择,只需要去记录就可以了,即选择每一轮的所能达到的贡献。

我们从自底向上推,那么对于ci,bi依赖的是下面选择1的回合数及其位置,这些是未知的。

在动态规划中未知的量,我们可以把他作为dp数组中的某一维,那么在求解的过程中我们就可以把他当作已知量

来暴力枚举每一种可能值。(如果时间允许的话)

因为这些未知量都是未知的条件,且都会对最终的答案产生影响。

所以在本题中,我们需要知道的是对于第i轮,第i+1...n轮中选择1的个数,以及他们的标号和。

因为对于bi,假定下面第p轮是选择1的,那么bi就会对第p轮造成贡献(p-i)*bi,那么如果下面有第p1,p2,p3,...pk轮选择1

,那么选择bi的贡献就是(p1+p2+p3+...+pk-k*i)*bi。

ci的贡献是k*ci

那么我们的dp数组就开成dp[101][101][5100]->dp[i][j][k]:表示在i+1...n轮中,有j轮选择1且选择1的编号和是k的最大的贡献和

 

这道题的难点就是将未知量转换成dp维数的思路,即构造这个dp数组,这应该也是大多数动规的难点所在。另外一个小的难点就是用bi的贡献的条件怎么转换成dp的某一维

 

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
 
typedef long long ll;
ll dp[2][101][5100];
int a[101],b[101],c[101];
 
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d",&a[i],&b[i],&c[i]);
        }
        memset(dp[0],0,sizeof(dp[0]));
        dp[0][1][n]=a[n];
        int now=0;
        for(int i=n-1;i>=1;i--)
        {
            int nex=now^1;
            memset(dp[nex],0,sizeof(dp[nex]));
            for(int j=1;j<=n-i;j++)
            {
                int vv=(n+n-j+1)*j/2;
                for(int k=1;k<=vv;k++)
                {
                    if(!dp[now][j][k]) continue;
                    dp[nex][j+1][k+i]=max(dp[now][j][k]+a[i],dp[nex][j+1][k+i]);
                    dp[nex][j][k]=max(dp[nex][j][k],dp[now][j][k]+1ll*j*c[i]);
                    dp[nex][j][k]=max(dp[nex][j][k],dp[now][j][k]+1ll*(k-j*i)*b[i]);
                }
            }
            now=nex;
        }
        ll ans=0;
        for(int j=1;j<=n;j++)
        {
            int vv=(n+n-j+1)*j/2;
            for(int k=1;k<=vv;k++)
            {
                ans=max(ans,dp[now][j][k]);
            }
        }
        printf("%lld\n",ans);
    }
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值