啊啊啊啊,这道题搞了一晚上,简直要疯了,其实就是一道很简单的背包DP,一眼就看出来了,但是各种修改每次都是55分,最后发现好像除了第一次以后都不能从j=0开始转移,就是说每次都必须选一项,其实也不是很懂发题解的人为什么空间优化之后只要把j=0给覆盖掉就好了,而不考虑以后的错误转移,应该是可以用数学证明的= =但是蒟蒻就是不会啊,所以以后这样的题还是仔细的考虑一下能不能空间优化吧,如果自己不去管那绝对足够了的空间复杂度,绝对不会浪费一晚上的QAQ。
#include<cstdio>//p1282多米诺骨牌
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
using namespace std;
int sum,up,a[1010],b[1010],dp[30000],maxc,tot,bound,ans,n;
int main()//dp,状态f[i][j]表示前i个达到j的最少步数,01背包
{
cin>>n;//可优化空间,还可常数优化
sum=0;//因为要判断是否可以到达,先赋初值为最大值
maxc=0;
memset(dp,0x3f,sizeof(dp));
dp[0]=0;
for (int i=1;i<=n;i++)
{
cin>>a[i]>>b[i];
sum+=a[i]+b[i];
}
tot=sum;
for (int i=1;i<=n;i++)
{
maxc+=max(a[i],b[i]);
bound=min(a[i],b[i]);
for (int j=maxc; j>=0; j--)
{
int tmp=50000; //tmp代表取此物品更优秀的方式,并且强制地取
if (j>=a[i]) tmp=dp[j-a[i]];
if (j>=b[i]) tmp=min(tmp,dp[j-b[i]]+1);
dp[j]=tmp;
}
}
sum>>=1;
while(1)
{
ans=min(dp[sum],dp[tot-sum]);
if (ans<30000) break;
sum--;
}
cout<<ans;
return 0;
}
本文分享了一道关于背包动态规划的经典题目解决过程,作者详细记录了从困惑到解决的心路历程,包括如何避免错误转移及空间优化技巧。

274

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



