90分求助
查看原帖
90分求助
133116
Xhesika_Frost楼主2021/2/23 15:58
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<algorithm>

using namespace std;

int n,a[201],sum,ans=1000000000,ans1,ans2,f[201][805];
bool p[201][805];

inline int mx(int x,int y) {
	if(abs(x) < abs(y)) return x;
	return y;
}

inline bool mx1(int x,int y) {
	if(abs(x) < abs(y)) return 1;
	return 0;
}

inline bool cmp(int x,int y) {
	return x > y;
}

int main() {
	memset(f,0x3f3f3f,sizeof(f));
	scanf("%d",&n);
	for(int i = 1;i <= n; i++)
		scanf("%d",&a[i]);
	sort(a+1,a+n+1,cmp);
	f[1][201] = a[1];
	p[1][201] = 0;
	f[1][199] = 0 - a[1];
	p[1][199] = 1;
	for(int i = 2;i <= n; i++)
		for(int j = 200 - i - 1;j <= 200 + i + 1; j++) {
			f[i][j] = mx(f[i-1][j+1] - a[i],f[i-1][j-1] + a[i]);
			p[i][j] = mx1(f[i-1][j+1] - a[i],f[i-1][j-1] + a[i]);
//			printf("%d %d %d %d\n",i,j,f[i][j],p[i][j]);
		}
	for(int i = 199;i <= 201; i++) {
		if(abs(f[n][i]) < ans) {
			sum = i;
			ans = abs(f[n][i]);
		}
	}
	for(int i = n;i >= 1; i--) {
		if(!p[i][sum]) ans1 += a[i],sum -= 1;
		else ans2 += a[i],sum += 1;
//		printf("%d %d\n",i,sum);
	}
	printf("%d %d",min(ans1,ans2),max(ans1,ans2));
	return 0;
} 

f[i][j]表示到第i位时a1与a2元素个数差为j(以200为基数,防止出现负数下标)时的最小差值的绝对值(a1和a2为实时更新的两部分兵)

p[i][j]记录答案路径,求最后答案

求代码错误或一组可调试的hack数据,谢谢

2021/2/23 15:58
加载中...