[第四场T3]Kas

题目描述

Kile和Pogi在街上捡到了N张钞票。在确定无法找到失主之后,两人决定将钞票平分。他们想要得到相同数量的钱,所以他们将这些钞票尽可能分成价值相等的两份。但是当钞票无法平分的时候会剩下一些。

由于他们不能将剩余的钞票留在街上,他们决定去附近的赌场并将所有剩下的钞票都押上,希望最终得到两倍的赌注。幸运的是他们真的让赌注翻倍了,于是Kile和Pogi平分了赢的钱。

由于极度兴奋,他们失去了计算能力,请你帮助他们计算出每人带回家了多少钱。

输入

第一行输入包含一个整数N(1≤N≤500)。表示钞票的张数。

接下来N行每行包含一个整数Ci。第i+1行的整数Ci表示第i张钞票的面额。保证N张钞票的总值不超过1e5。

输出

输出一个整数。表示两人分别带回家的钱。

前方高能

解题思路

很明显嘛,DP,然而并不会打。考场搞半天,弄出来一个玄学的,本来暴力可以50,结果又因为绑点,玄学操作搞得1分都没有...

首先考虑三维

dp[i][j][k]表示用前i张钱可不可以令第一个人取j元,第二个人取k元。显然这样弄70分就有了。

显然空间时间要爆炸。

我们再考虑一下。

dp[i][j]表示用前i张钱令两人取的钱的差值为j的取的钱的总和最大值。

有些东西还是自己想会好做一下,

相信dp定义一出来还是很容易推的。

70分:

#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
int n,c[100005],sum;
bool dp[505][1005][1005];
int main(){
	//freopen("kas.in","r",stdin);
//	freopen("kas.out","w",stdout);
	scanf("%d",&n);
	for (int i = 1;i <= n;i ++){
		scanf ("%d",&c[i]);
		sum += c[i];
	}
	dp[0][0][0] = 1;
	for (int i = 1;i <= n;i ++){
		for (int j = 0;j <= sum;j ++){
			for (int k = 0;k <= sum;k ++){
				if (j >= c[i])
					dp[i][j][k] = max(dp[i][j][k],dp[i - 1][j - c[i]][k]);
				if (k >= c[i])
					dp[i][j][k] = max(dp[i][j][k],dp[i - 1][j][k - c[i]]);
				dp[i][j][k] = max(dp[i][j][k],dp[i - 1][j][k]);
			}
		}
	}
	for (int i = sum;i >= 0;i --){
		if (dp[n][i][i]){
			printf("%d
",sum - i);
			return 0;
		}
	}
}

100分:

这里有一个清空问题,本人是这样理解的。

#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
int n,c[100005],sum;
int dp[505][100005];
int main(){
	//freopen("kas.in","r",stdin);
	//	freopen("kas.out","w",stdout);
	scanf("%d",&n);
	for (int i = 1;i <= n;i ++){
		scanf ("%d",&c[i]);
		sum += c[i];
	}
	memset(dp,-0x3f,sizeof(dp));//这里为何要清负数?因为可能你在转移的时候,有一些DP的值根本没有更新。
	//然而你如果仅仅是0,加上c[i]就有可能大于当前DP,因而做出了一个错误的转移
	dp[0][0]=0;
	for (int i = 1;i <= n;i ++){
		for(int j = 0;j <= sum;j ++){
			dp[i][j] = dp[i - 1][j];
			dp[i][j] = max(dp[i - 1][j + c[i]] + c[i],dp[i][j]);
			dp[i][j] = max(dp[i - 1][abs(j - c[i])] + c[i],dp[i][j]);
		}
	}
	printf("%d",sum - dp[n][0] / 2);
}
原文地址:https://www.cnblogs.com/lover-fucker/p/13566670.html