这次的比赛可以说是很骚了。
开头的两题我大概都有思路,花了两个半小时左右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;
}