首页 > 代码库 > acdream 1429 Rectangular Polygon【dp】
acdream 1429 Rectangular Polygon【dp】
题目:acdream 1429 Rectangular Polygon
题意:给出n个数,是边长,然后问你能不能组成多边形,其边必须是平行于x轴或者平行于y轴的。如果可以的话输出任意一种方案。
分析:分析发现,就是给你一堆数,然后让你尽可能挑出多的数,分成两部分的和相等,我们可以用dp来解决这个问题。
定义dp【i】【j】 前 i 个数中挑出一些书其两部分的差值是 j 的最大个数。
转移方程:
dp[i][j] = max(dp[i][j],dp[i-1][j]); //不放 dp[i][j-a[i]] = max(dp[i][j-a[i]],dp[i-1][j]+1); //放入第二堆 dp[i][j+a[i]] = max(dp[i][j+a[i]],dp[i-1][j]+1); //放入第一堆
然后记录路径,输出来就可以了。
AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; typedef long long ll; const int N = 55000; const int M = 125; int num[M]; bool ok[N]; int dp[M][N]; int fa[M][N]; vector<int> one,two; int main() { //freopen("Input.txt","r",stdin); int n; while(~scanf("%d",&n)) { int sum = 0; for(int i = 1; i <= n; i++) { scanf("%d", &num[i]); sum += num[i]; } int l = 30000 , r = 30000 ; memset(dp, -1, sizeof(dp)); dp[0][30000] = 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]; fa[i][j] = j; } if(dp[i][j+num[i]] < dp[i-1][j] + 1) { dp[i][j + num[i]] = dp[i-1][j] + 1; fa[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; fa[i][j - num[i]] = j; } } l-=num[i]; r+=num[i]; } printf("%d\n", dp[n][30000]); int t = 30000; for(int i = n; i >= 1; i -- ) { int tmp = fa[i][t]; if(t > tmp) one.push_back(t - tmp); if(t < tmp) two.push_back(tmp - t); t = tmp; } int x, y; x = 0; y = 0; for(int i = 0; i < two.size(); i++) { y++; printf("%d %d\n", x, y); x += two[i]; printf("%d %d\n", x, y); } y = 0; for(int i = 0; i < one.size(); i++) { y--; printf("%d %d\n", x, y); x -= one[i]; printf("%d %d\n", x, y); } one.clear(); two.clear(); } return 0; }
分析:分析发现,就是给你一堆数,然后让你尽可能挑出多的数,分成两部分的和相等,我们可以用dp来解决这个问题。
acdream 1429 Rectangular Polygon【dp】
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。