题目描述
两个人在街上捡到了一些钱,这些钱共有N张,他们等了很久也没有等来失主,于是决定把钱平分。但钱可能无法平分。他们先把能够平分的钱尽量先平分了,使得剩下不能平分的钱尽量少。这些不能平分的钱怎么办呢他?他们决定拿去赌场里面赌一把。他们运气太好了,那些不能平分的钱变成了双倍,于是他们就把那个钱分了。现在,请问他们每个人带回家多少钱。
输入格式
第一行包含一个整数N(1<=N<=500),表示他们捡到N 张。
接下来N行,每行包含一个正整数ci,表示第i张钱的面值。总金额不超过100000。
输出格式
你输出他们每个人能回家多少钱。
输入样例
5
2
3
5
8
13
输出样例
18
题解:dp[i][j]:前i张钱分两堆, 两堆差为j时,较大堆的值
#include<cstdio> #include<cstring> #define max( a, b ) ( a>b ? a : b ) const int N=505; const int M=100005; int n, m[N], dp[N][M], sum; int main() { scanf( "%d", &n ); for( int i=1; i<=n; i++ ) scanf( "%d", &m[i] ), sum+=m[i]; memset( dp, -0x3f, sizeof dp ); dp[0][0]=0; for( int i=1; i<=n; i++ ) for( int j=0; j<=(sum>>1); j++ ) { dp[i][j]=max( dp[i-1][j], dp[i-1][ j+m[i] ] );//不放or放较小堆, 两堆大小不变 if( j>=m[i] ) dp[i][j]=max( dp[i][j], dp[i-1][ j-m[i] ]+m[i] );//放较大堆 if( j<=m[i] ) dp[i][j]=max( dp[i][j], dp[i-1][ m[i]-j ]+j );//放较小堆, 两堆大小交换 } printf( "%d\n", sum-dp[n][0] ); return 0; }
[NOIP模拟赛]分钱
最新推荐文章于 2019-04-26 17:49:00 发布