CF1176F Destroy it!题解

7 篇文章 0 订阅
6 篇文章 0 订阅

题目大意:给定n个块,每个块内给你m个操作,其花费为w,攻击为v。每个块内不得选w总和超过3的操作(可以不选),总计选到第x个(x为10的倍数)时v可以翻倍,求v总和最大值
题解:一道简单到连我都能做出来的 DP
其实就是01背包的变式,多了一个v翻倍操作
设F[i][j]为做到第i个块,选了j个操作
因为空间不够,j%=10,这样不影响计算。
其实只有这么几个转移:{1,1,1},{1,1},{1},{1,2},{2},{3},(集合内代表w),直接做就好了
注意:可以不选,这些转移不一定可行,需要判断

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long 
using namespace std;
ll f[200005][15];
ll i,j,k,m,n,o,p,l,s,t,times,max1,max2,max3,max4,max5;
void read(ll &x)
{
	char ch=getchar();x=0;
	while (ch<'0'||ch>'9') ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=getchar();
} 
int main()
{
//	freopen("destroy.in","r",stdin);
//	freopen("destroy.out","w",stdout);
	read(n);
	memset(f,-60,sizeof(f));f[0][0]=0;
	for (i=1;i<=n;i++)
	{
		read(m);max1=max2=max3=max4=max5=0;
		for (j=1;j<=m;j++) {
			read(o);read(p);
			if (o==1) {
				if (p>=max1) max3=max2,max2=max1,max1=p;
				else if (p>=max2) max3=max2,max2=p;
				else max3=max(max3,p);
			} else if (o==2) max4=max(max4,p);
			else max5=max(max5,p);
		}
		for (j=0;j<=9;j++) f[i][j]=f[i-1][j];
		for (j=1;j<=3;j++)
		{
			for (k=0;k<=9;k++)
			{
				if (j==1)
				{
					if (f[i-1][k]>=0)
					{
						if (max1) f[i][(k+1)%10]=max(f[i][(k+1)%10],f[i-1][k]+max1*(1+(k==9)));
					}
				} else if (j==2)
				{
					if (f[i-1][k]>=0)
					{
						if (max1&&max2) f[i][(k+2)%10]=max(f[i][(k+2)%10],f[i-1][k]+max1*(1+(k>=8))+max2);
						if (max4) f[i][(k+1)%10]=max(f[i][(k+1)%10],f[i-1][k]+max4*(1+(k>=9)));
					}
				} else if (j==3)
				{
					if (f[i-1][k]>=0)
					{
						if (max1&&max2&&max3) f[i][(k+3)%10]=max(f[i][(k+3)%10],f[i-1][k]+max1*(1+(k>=7))+max2+max3);
						if (max1&&max4) f[i][(k+2)%10]=max(f[i][(k+2)%10],f[i-1][k]+max(max1,max4)*(1+(k>=8))+min(max1,max4));
						if (max5) f[i][(k+1)%10]=max(f[i][(k+1)%10],f[i-1][k]+max5*(1+(k>=9)));
					} 
				}
			}
		}
	}
	s=0;
	for (i=0;i<=9;i++) s=max(s,f[n][i]);
	printf("%lld\n",s);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值