04.07 dp练习赛 总结

        这次的比赛可以说是很骚了。

        开头的两题我大概都有思路,花了两个半小时左右ac了。那么剩下的六题,一天的时间我一题都没写出来!

        当然我个人的心态可能是有问题的,看着别人一题一题的ac,说不着急是不可能的。但是我认为大部分还是我个人能力的问题。我写的代码都没有什么技巧性,所以,理所当然的tle甚至mle都出现了,关键问题是我找不到任何优化的方法。后来分析的时候才恍然大悟,原来是用一种自己从来没有想到的方法来解决的。

        我一直觉得我对dp掌握的还可以,这次练习之后才认识到自己的不足,那么接下来就是要对症下药了。

        这里放一题的解析吧。(因为这题把我坑死)

        这题我一开始是把所有可能的状态用数组存起来再找最大值,但是这样又爆空间又爆时间,而且这种方法是无法优化的,所以我交了十多遍都没有过。

        后来听讲解说是要转化成一个背包问题。ai作为价值v,a[i]-k*b[i]作为重量w,dp[i]表示当重量为i时的最大值。但是这样w有可能就是负数,那么就将所有的重量都加上1000。但是问题在于怎么求得最大值呢?很不幸,我不会。

        那么我就想了另外一个办法,当重量w>=0的时候循环是从后往前的,w<0的时候循环是从前往后的,那么就可以判断一下wi的正负,分成两种不同的状况,那么由于要整除,最大值就是dp[0]。

        代码如下

#include<bits/stdc++.h>
using namespace std;
struct node
{
	int w;
	int v;
}a[250];
int n,k;
int C=0;
int dp[100010];
int kk[100010]={};
int ans=-1;
bool mycmp(node x,node y)
{
	return (x.w>y.w);
}
void init()
{
	memset(dp,-1,sizeof(dp));
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	cin>>a[i].v;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].w;
		a[i].w=a[i].v-k*a[i].w;
		C+=abs(a[i].w);
	}
}
void work()
{
	sort(a+1,a+1+n,mycmp);
	dp[0]=0;
	for(int i=1;i<=n;i++)
	{
		if(a[i].w>=0) {
			for(int j=C;j>=a[i].w;j--)
			{	if(dp[j-a[i].w]>=0) dp[j]=max(dp[j],dp[j-a[i].w]+a[i].v);}
		}
		else{
			for(int j=0;j<=C;j++)
			{	if(dp[j-a[i].w]>=0) dp[j]=max(dp[j],dp[j-a[i].w]+a[i].v); }
		}
	}
	if(dp[0]>0) ans=max(ans,dp[0]);//由于无方案时要输出-1,所以需要判断一下
	cout<<ans<<endl;
}
				
int main()
{
	init();
	work();
	return 0;
}
        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值