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来解决这个问题。

时间: 2024-12-10 20:24:31

acdream 1429 Rectangular Polygon【dp】的相关文章

ACdream 1429 Rectangular Polygon

Rectangular Polygon Time Limit: 1000MS   Memory Limit: 256000KB   64bit IO Format: %lld & %llu Description A rectangular polygon is a polygon whose edges are all parallel to the coordinate axes. The polygon must have a single, non-intersecting bounda

【ASC 23】G. ACdream 1429 Rectangular Polygon --DP

题意:有很多棍子,从棍子中选出两个棍子集合,使他们的和相等,求能取得的最多棍子数. 解法:容易看出有一个多阶段决策的过程,对于每个棍子,我们有 可以不选,或是选在第一个集合,或是选在第二个集合 这三种决策.因为两个集合最后的和要相等,那么令一个集合为正,另一个为负,那么最后和为0,我们用偏移0的量来作为状态之一. dp[i][j]表示前 i 个 偏移量为 j 的最大棍子数,因为每根棍最长为200,所以偏移量最多为+-20000,所以在+-20000之间枚举,最多100*40000 代码: #in

HDU2391 Filthy Rich 【DP】

Filthy Rich Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1793    Accepted Submission(s): 815 Problem Description They say that in Phrygia, the streets are paved with gold. You're currently

hdoj 2391 Filthy Rich 【DP】

题目大意:有个二维数组,你从(0,0)出发,最终到(n,m), 在这个二维数组中,每个位置dp[i][j]都有一定量的黄金,你可以拾取,问你最多能失去多少,并且,你的方向有下,右, 斜向下三个方向: 策略:就是每一个都加上它的上方向与左方向的最大值,这样到最后就是最大值.详情见代码 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2391 代码: #include<stdio.h> #include<string.h> int dp[1

HDOJ1176 免费馅饼 【DP】+【经典数塔】

免费馅饼 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 23986    Accepted Submission(s): 8093 Problem Description 都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼.说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的1

nyoj 325 zb的生日 【DP】||【DFS】

两种方法: 第一种:将总数一半当做背包,用总数-2*最多能装的数目就是所求: 第二种:深搜: zb的生日 时间限制:3000 ms  |  内存限制:65535 KB 难度:2 描述 今天是阴历七月初五,acm队员zb的生日.zb正在和C小加.never在武汉集训.他想给这两位兄弟买点什么庆祝生日,经过调查,zb发现C小加和never都很喜欢吃西瓜,而且一吃就是一堆的那种,zb立刻下定决心买了一堆西瓜.当他准备把西瓜送给C小加和never的时候,遇到了一个难题,never和C小加不在一块住,只能

HDOJ4540 威威猫系列故事——打地鼠 【DP】

威威猫系列故事--打地鼠 Time Limit: 300/100 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 1445    Accepted Submission(s): 713 Problem Description 威威猫最近不务正业,每天沉迷于游戏"打地鼠". 每当朋友们劝他别太着迷游戏,应该好好工作的时候,他总是说,我是威威猫,猫打老鼠就是我的工作! 无话

NYOJ16 矩形嵌套 【DP】

矩形嵌套 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 有n个矩形,每个矩形可以用a,b来描述,表示长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度).例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中.你的任务是选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内. 输入 第一行是一个正正数N(0<N<10),表示测试数据组数, 每组

hdoj 2046 骨牌铺方格 【DP】+【斐波那契】

dp果然不是好学的... 第n个,即2*n时,可由第n-1个的竖直排列再加一个,和第n-2个中横着排两个 所以f(n) = 1×f(n-1) + 1×f(n-2): 骨牌铺方格 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 28412    Accepted Submission(s): 13771 Problem Descripti