Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

一个下午WA了10把 终于在吃饭前的最后一把AC了。简单说下解题思路。

Posted by dearbear at 2009-07-20 20:16:50 on Problem 1717
这题在网上搜解题报告不理想。写的都很搓。导致我独自背了一个下午的背包。

这题就是普通的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:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator