nbu 2414 Please help the poor donkey!

Please help the poor donkey!

Time Limit : 1000 MS | Memory Limit : 65536 KB

Submits : 27 | Solved : 3

Description

A donkey is on his way home with many goods hanging on the two side of his back ,tired and thirsty . What a poor donkey ! What's worse , the total weight of the goods on each side of his back doesn't have the same value , which makes the poor donkey much more difficult to keep balance .Now I should to help the poor donkey move some goods from one side to another to ease his burden . I want to minimize the difference of the total weight between the two sides .Of course I'm very lazy ,could you tell me the minimum number of the goods that I need to move to minimize the difference of the total weight betwoon the two sides. If you tell me the correct answer , I will give you an 'AC' !


Input

Input contains multiple test cases. The first line of each test cases contains two integers n and m , n indicates the number of the goods hanging on the left side of the donkey, m indicates the number of the goods hanging on the right side of the donkey.(0<n+m<=1000)
The second line of the test case contains n integers indicating the weight of the n goods on the left side .
The third line contains m integers indicating the weight of the m goods on the right .


Output

Output the minimum number of the goods that I need to move .


Sample Input

1 3
5 
4 2 1


Sample Output

1

分析:先把所有的数存到一个一位数组(下标从1到n+m)
dp[i][j]:表示前i个数组成和为j最少移动多少次(这里可以以一边为准,比如代码里选择第一行所代表的一边)
转移方程:
                  dp[i][j]=dp[i-1][j];//先从前一个继承过来,表示当前无操作
                  if(i>n)dp[i][j+a[i]]=min(dp[i][j+a[i]],dp[i-1][j]+1);//是另外一边,如果操作,只能把它移到这边,故j+a[i]
                  else dp[i][j-a[i]]=min(dp[i][j-a[i]],dp[i-1][j]+1);//是这边,如果操作,只能把它移到另一边,故j-a[i]
#include<cstdio>
const int N=1001;
int a[N],dp[N][N<<2];
int min(int a,int b){
	if(a==-1)return b;
	if(b==-1)return a;
	return a<b?a:b;
}
int abs(int a){return a<0?-a:a;}
int main(){
	int n,m,i,j,lsum,sum;
	while(~scanf("%d%d",&n,&m)){
		lsum=0,m+=n;
		for(i=1;i<=n;i++)scanf("%d",a+i),lsum+=a[i];
		sum=lsum;
		for(;i<=m;i++)scanf("%d",a+i),sum+=a[i];
		for(i=0;i<=sum;i++)dp[0][i]=-1;
		dp[0][lsum]=0;
		for(i=1;i<=m;i++){
			for(j=0;j<=sum;j++)dp[i][j]=dp[i-1][j];
			for(j=0;j<=sum;j++)if(dp[i-1][j]!=-1){
				if(i>n)dp[i][j+a[i]]=min(dp[i][j+a[i]],dp[i-1][j]+1);
				else dp[i][j-a[i]]=min(dp[i][j-a[i]],dp[i-1][j]+1);
			}
		}
		int ans;
		for(i=sum>>1;i>=0;i--){
			if(dp[m][i]!=-1||dp[m][sum-i]!=-1){ans=min(dp[m][i],dp[m][sum-i]);break;}
		}
		printf("%d\n",ans);
	}
	return 0;
}

滚动数组
#include<cstdio>
const int N=1001;
int a[N],dp[2][N<<2];
int min(int a,int b){
	if(a==-1)return b;
	if(b==-1)return a;
	return a<b?a:b;
}
int abs(int a){return a<0?-a:a;}
int main(){
	int n,m,i,j,lsum,sum;
	while(~scanf("%d%d",&n,&m)){
		lsum=0,m+=n;
		for(i=1;i<=n;i++)scanf("%d",a+i),lsum+=a[i];
		sum=lsum;
		for(;i<=m;i++)scanf("%d",a+i),sum+=a[i];
		for(i=0;i<=sum;i++)dp[0][i]=-1;
		dp[0][lsum]=0;
		int now=0;
		for(i=1;i<=m;i++){
			now^=1;
			for(j=0;j<=sum;j++)dp[now][j]=dp[now^1][j];
			for(j=0;j<=sum;j++)if(dp[now^1][j]!=-1){
				if(i>n)dp[now][j+a[i]]=min(dp[now][j+a[i]],dp[now^1][j]+1);
				else dp[now][j-a[i]]=min(dp[now][j-a[i]],dp[now^1][j]+1);
			}
		}
		int ans;
		for(i=sum>>1;i>=0;i--){
			if(dp[now][i]!=-1||dp[now][sum-i]!=-1){ans=min(dp[now][i],dp[now][sum-i]);break;}
		}
		printf("%d\n",ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值