• CF1167F Solution


    题目链接

    题解

    ⭐:(inf)若需多次加减不宜过大,容易溢出。

    dp题呐~

    状态:(dp[i][j])表示前(i)轮距离上次(包括当前卡牌)触发双倍已经经过(j)张卡时的最大伤害。

    初始值:(dp[i][j]=inf,dp[i][0]=0quad (0le ile n,1le jle 9))

    转移方程:设(x1,x2,x3)分别为(c=1)卡牌的最大、次大、第三大(d)值,(y,z)分别为(c=2,3)卡牌的最大(d)值。

    [dp[i][j]=dp[i-1][j]\ dp[i][(j+3)\%10]=max(dp[i][(j+3)\%10],dp[i-1][j]+x1*2+x2+x3)quad (jge 7)\ dp[i][j+3]=max(dp[i][j+3],dp[i-1][j]+x1+x2+x3)quad (j<7)\ dp[i][(j+2)\%10]=max(dp[i][(j+2)\%10],dp[i-1][j]+max(x1*2+x2,x1*2+y,y*2+x1))quad (jge 8)\ dp[i][j+2]=max(dp[i][j+2],dp[i-1][j]+max(x1+x2,y+x1))quad (j<8)\ dp[i][0]=max(dp[i][0],dp[i-1][j]+max(x1,max(y,z))*2)quad (j=9)\ dp[i][j+1]=max(dp[i][j+1],dp[i-1][j]+max(x1,y,z))quad (j<9)\ (1le ile n,9ge jge 0) ]

    好长,但基本思路就是1行为不选的转移方程,2,4,6行为触发双倍时的方程,其余为普通转移。注意(j)需倒序枚举,否则会从当前回合的状态转移而来。

    目标状态:(max_{i=0}^{ile 9} dp[n][i])

    AC代码

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=2e5+10,inf=0x7fffffff;
    struct node {int c,d;} a[N];
    int dp[N][15];
    signed main()
    {
    	int n,k,ans=0;
    	scanf("%lld",&n);
        //初始化
    	for(int i=0;i<=n;i++)
    		for(int j=0;j<=9;j++) dp[i][j]=-inf;
    	for(int i=0;i<=n;i++) dp[i][0]=0;
        //dp
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%lld",&k);
    		for(int j=1;j<=k;j++) scanf("%lld%lld",&a[j].c,&a[j].d);
            //贪心求出x1,x2,x3,y,z
    		int x1=-inf,x2=-inf,x3=-inf,y=-inf,z=-inf;
    		for(int j=1;j<=k;j++)
    		{
    			if(a[j].c==1)
    			{
    				if(a[j].d>x1) x3=x2,x2=x1,x1=a[j].d;
    				else if(a[j].d>x2) x3=x2,x2=a[j].d;
    				else if(a[j].d>x3) x3=a[j].d;
    			}
    			else if(a[j].c==2) y=max(y,a[j].d);
    			else z=max(z,a[j].d);
    		}
            //转移
    		for(int j=9;j>=0;j--) dp[i][j]=dp[i-1][j];
    		for(int j=9;j>=0;j--)
    		{
    			if(j>=7) dp[i][(j+3)%10]=max(dp[i][(j+3)%10],dp[i-1][j]+x1*2+x2+x3);
    			else dp[i][j+3]=max(dp[i][j+3],dp[i-1][j]+x1+x2+x3);
    			if(j>=8) dp[i][(j+2)%10]=max(dp[i][(j+2)%10],dp[i-1][j]+max(x1*2+x2,max(x1*2+y,y*2+x1)));
    			else dp[i][j+2]=max(dp[i][j+2],dp[i-1][j]+max(x1+x2,y+x1));
    			if(j==9) dp[i][0]=max(dp[i][0],dp[i-1][j]+max(x1,max(y,z))*2);
    			else dp[i][j+1]=max(dp[i][j+1],dp[i-1][j]+max(x1,max(y,z)));
    		}
    	}
        //统计答案
    	for(int i=0;i<=9;i++) ans=max(ans,dp[n][i]);
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    自定义异常
    java代码中正则表达式
    mybatis中代码如何实现批量添加
    List集合的三种遍历方式的效率问题
    4种方式配置不同作用域的jvm的堆栈内存!
    如何在Eclipse里修改端口
    如何用Eclipse打jar包
    用explain来解析sql语句,然后建立正确的索引
    quartz简单demo,教你最快使用quartz
    log4j.properties配置详解
  • 原文地址:https://www.cnblogs.com/violetholmes/p/14607442.html
Copyright © 2020-2023  润新知