题目:LINK
一共n个木棒,要求摆成ectangular polygon,木棒只能水平摆放。
可以精简为, 给你n(n<=100) 个数,每个数xi(xi<=200) ,要求从中拿出x个数,设和为s1, 在剩下的再拿出y个数,设和s2,要求s1 == s2,求满足这个条件下x+y的最大值是什么。
dp[i][j] 处理完第i个数,差值为j时的用的数字个数,由于j可能是负数,要加上N.
dp[i][j] = dp[i-1][j], dp[i][j+num] = dp[i-1][j]+1; dp[i][j-num] = dp[i-1][j] + 1;
记录路径,之后把输出搞一下就好了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define INF 1000000000
//typedef __int64 LL;
#define N 20010
int n, num[121];
int dp[121][50015];
int path[121][50015];
vector< int > save1, save2;
int main() {
scanf("%d", &n) ;
int sum = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &num[i]); sum += num[i];
}
int l = N - sum, r = N + sum;
memset(dp, -1, sizeof(dp));
dp[0][N] = 0;
for(int i = 1;i <= n; i++) {
for(int j = l; j <= r; j++) {
if(dp[i-1][j] <= -1) continue;
if(dp[i][j] < dp[i-1][j]) {
dp[i][j] = dp[i-1][j];
path[i][j] = j;
}
if(dp[i][j+num[i]] < dp[i-1][j] + 1) {
dp[i][j + num[i]] = dp[i-1][j] + 1;
path[i][j + num[i]] = j;
}
if(dp[i][j - num[i]] < dp[i-1][j] + 1) {
dp[i][j - num[i]] = dp[i-1][j] + 1;
path[i][j - num[i]] = j;
}
}
}
printf("%d\n", dp[n][N]);
save1.clear(); save2.clear();
int t = N;
for(int i = n; i >= 1; i -- ) {
int tmp = path[i][t];
if(t > tmp) save1.push_back(t - tmp);
if(t < tmp) save2.push_back(tmp - t);
t = tmp;
}
int x, y;
x = 0; y = 0;
for(int i = 0; i < save2.size(); i++) {
y++;
printf("%d %d\n", x, y);
x += save2[i];
printf("%d %d\n", x, y);
}
y = 0;
for(int i = 0; i < save1.size(); i++) {
y--;
printf("%d %d\n", x, y);
x -= save1[i];
printf("%d %d\n", x, y);
}
return 0;
}