这次的比赛可以说是很骚了。
开头的两题我大概都有思路,花了两个半小时左右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;
}
本文分享了一次编程比赛中遇到的动态规划难题经历,作者通过不断尝试最终找到了将问题转化为背包问题的有效解决方案,并给出了详细的代码实现。
4582

被折叠的 条评论
为什么被折叠?



