| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
一个下午WA了10把 终于在吃饭前的最后一把AC了。简单说下解题思路。这题在网上搜解题报告不理想。写的都很搓。导致我独自背了一个下午的背包。
这题就是普通的0-1背包问题。
难点就在于变形。
我用点数来刷背包DP 容量即为总点数sum 物品容量则是 每次对换点数之差为g
I问题就在于g的值有正负,所以刷背包时要注意数组下标多加10000左右,即0表示为10000。这样处理正负比较容易。还要说的是因为Q正负的缘故,我把刷背包分为两段,正负分开。
II问题出现在最后查找最小值的时候。逻辑要清晰。
代码如下。 比搜索结果里的博客写的好哇。^^自我陶醉。
#include <iostream>
#define S 10000
using namespace std;
int dp[16100];
int ABS(int n)
{
if(n<0)
return -n;
else
return n;
}
int main()
{
int n,i,g,j,sum,k,ans,t,f;
int o[1100],p[1100],min;
while(cin>>n)
{
sum=0;
k=0;
for(i=1;i<=n;i++)
{
cin>>o[i]>>p[i];
sum+=o[i]+p[i];
k+=o[i];
}
k=k+S;
t=k;
for(i=0;i<=sum+S;i++)
dp[i]=999999;
dp[k]=0;
for(i=1;i<=n;i++)
{
g=p[i]-o[i];
if(g<0)
{
for(j=S-g;j<=sum+S;j++)
if(dp[j+g]>dp[j]+1)
dp[j+g]=dp[j]+1;
}
else
{
for(j=S+sum;j>=S+g;j--)
if(dp[j-g]+1<dp[j])
dp[j]=dp[j-g]+1;
}
}
ans=999999;
min=999999;
for(i=S;i<=S+sum;i++)
{
if(dp[i]!=999999)
{
if(min>ABS(sum-2*(i-S)))
{
ans=dp[i];
min=ABS(sum-2*(i-S));
}
else if(min==ABS(sum-2*(i-S)))
{
if(ans>dp[i])
ans=dp[i];
}
}
}
cout<<ans<<endl;
}
return 0;
}
Followed by:
Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator