Problem G. Rectangular Polygon(dp + 转移重现)

原创 2017年10月13日 20:30:56

2006-2007 Winter Petrozavodsk Camp, Andrew Stankevich Contest 23 (ASC 23)

Problem G. Rectangular Polygon
Input file: polygon.in
Output file: polygon.out
Time limit: 1 second
Memory limit: 64 megabytes
A rectangular polygon is a polygon whose edges are all parallel to the coordinate axes. The polygon
must have a single, non-intersecting boundary. No two adjacent sides must be parallel.
Johnny has several sticks of various lengths. He would like to construct a rectangular polygon. He is
planning to use sticks as horizontal edges of the polygon, and draw vertical edges with a pen.
Now Johnny wonders, how many sticks he can use. Help him, find the maximal number of sticks that
Johnny can use. He will use sticks only as horizontal edges.
Input
The first line of the input file contains n — the number of sticks (1 ≤ n ≤ 100). The second line contains
n integer numbers — the lengths of the sticks he has. The length of each stick doesn’t exceed 200.
Output
Print l — the number of sticks Johnny can use at the first line of the output file. The following 2l lines
must contain the vertices of the rectangular polygon Johnny can construct. Vertices must be listed in
order of traversal. The first two vertices must be the ends of a horizontal edge. If there are several
solution, output any one. Vertex coordinates must not exceed 109
.
If no polygon can be constructed, output l = 0.
Example
polygon.in polygon.out
4
1 2 3 5
3
0 0
1 0
1 1
3 1
3 2
0 2
4
1 2 4 8
0
4
1 1 1 1
4
0 0
1 0
1 1
2 1
2 -2
1 -2
1 -1
0 -1
In the first example Johnny uses a stick of length 1 for (0, 0)−(1, 0) edge, a stick of length 2 for (1, 1)−(3, 1)
edge and a stick of length 3 for (3, 2) − (0, 2) edge. There is no way to use all four sticks.

题意等价于:给你n个砝码,第i个砝码的重量为wi,问:最多选多少个砝码使天平平衡。
#include<bits/stdc++.h>
using namespace std;

const int maxn = 4e4 + 5;


struct X{
    int pre;     当前的状态时由上一个哪个状态转移来的
    int sum;
}dp[105][maxn];  dp[i][j].sum : 前 i 个砝码,偏移度为 j 最多拿多少个砝码。

                 若左边秤更重时 j(向左偏移 j 重量)就为负数,若右边秤更重时j(向左偏移 j 重量)为正数,
                 若天平平衡时 j 为0。

                 因为数组的 j 不能为负数,所以就整体向右平移20000,天平平衡时 j 为20000。

                 因为n最大为100,每个砝码最大为200,如果都放在左边 j 就为-20000。

                 所以最后答案为:dp[n][20000];

int w[105];      砝码的重量。
int l[105];      放左边砝码的重量。
int r[105];      放右边砝码的重量。

void Init(int n){初始化
    for(int i = 0;i <= n;i++){
        for(int j = 0;j <= 40000;j++){
            dp[i][j].sum = -100000000;
        }
    }
    dp[0][20000].sum = 0;
}

int main(){
    freopen("polygon.in","r",stdin);
    freopen("polygon.out","w",stdout);
    int n;
    scanf("%d",&n);
    for(int i = 1;i <= n;i++) scanf("%d",&w[i]);
    Init(n);
    for(int i = 1;i <= n;i++){
        for(int j = 0;j <= 40000;j++){
            if(j >= w[i] && j + w[i] <= 40000){
                int a,b,c,M;
                a = dp[i - 1][j - w[i]].sum + 1;//第 i 个砝码放右边。
                b = dp[i - 1][j + w[i]].sum + 1;//第 i 个砝码放左边。
                c = dp[i - 1][j].sum;           //第 i 个砝码不放。
                M = max(a,max(b,c));
                if(M == a) dp[i][j].pre = j - w[i];
                else if(M == b) dp[i][j].pre = j + w[i];
                else if(M == c) dp[i][j].pre = j;
                dp[i][j].sum = M;
            }
            else if(j >= w[i]){
                int a,b,M;
                a = dp[i - 1][j - w[i]].sum + 1;//第 i 个砝码放右边。
                b = dp[i - 1][j].sum;           //第 i 个砝码不放。
                M = max(a,b);
                if(M == a) dp[i][j].pre = j - w[i];
                else if(M == b) dp[i][j].pre = j;
                dp[i][j].sum = M;
            }
            else if(j + w[i] <= 40000){
                int a,b,M;
                a = dp[i - 1][j + w[i]].sum + 1;//第 i 个砝码放右边。
                b = dp[i - 1][j].sum;           //第 i 个砝码不放。
                M = max(a,b);
                if(M == a) dp[i][j].pre = j + w[i];
                else if(M == b) dp[i][j].pre = j;
                dp[i][j].sum = M;
            }
            else{
                dp[i][j].sum = dp[i - 1][j].sum;//第 i 个砝码不放。
                dp[i][j].pre = j;
            }
        }
    }

    int ll = 0,rr = 0,tot = 20000;//把左右边秤的砝码挑出来。
    for(int i = n;i >= 1;i--){
        int ans = dp[i][tot].pre - tot;
        if(ans > 0) l[++ll] = ans; 
        else if(ans < 0) r[++rr] = -ans;
        tot = dp[i][tot].pre;
    }

    printf("%d\n",dp[n][20000].sum);
    if(dp[n][20000].sum != 0){//选的砝码的个数不为0就输出。
        int x,y;
        x = l[1],y = 0;
        printf("0 0\n");
        printf("%d %d\n",x,y);
        for(int i = 2;i <= ll;i++){
            y++;
            printf("%d %d\n",x,y);
            x += l[i];
            printf("%d %d\n",x,y);
        }
        y++;
        printf("%d %d\n",x,y);
        x -= r[1];
        printf("%d %d\n",x,y);
        for(int i = 2;i <= rr;i++){
            y++;
            printf("%d %d\n",x,y);
            x -= r[i];
            printf("%d %d\n",x,y);
        }
    }
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

状态压缩dp入门 第一题 POJ 3254 Corn Fields

Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6460   Accepted: 3436...
  • LYHVOYAGE
  • LYHVOYAGE
  • 2014年04月29日 09:41
  • 3687

DP问题各种模型的状态转移方程

1(最长公共子串(注意和最长公共子序列区别))两个字符串str1和str2,长度分别为(l1,l2)dp[i][j]表示以两个字符串分别以第i和第j个字符结尾所能达到的公共子序列的长度,由于下面涉及到...
  • sun897949163
  • sun897949163
  • 2015年11月01日 16:55
  • 1590

CSS中那些px、em、pt、rem、%、dp(android)单位

未经允许,不得转载!! 水平有限,写的不周之处欢迎指正、交流! 在前端开发中,遇到单位的时候会有几种选择,那到底用哪种单位才是最合适的呢? 在国内的一些美工设计大师,在设计的时候多偏向于px单位,...
  • ime33
  • ime33
  • 2017年01月14日 10:28
  • 3071

acdream 1429 Rectangular Polygon【dp】

题目:acdream 1429 Rectangular Polygon 题意:给出n个数,是边长,然后问你能不能组成多边形,其边必须是平行于x轴或者平行于y轴的。如果可以的话输出任意一种方案...
  • y990041769
  • y990041769
  • 2014年12月01日 19:43
  • 1088

acdream1429 rectangular polygon

动态规划
  • sdfzyhx
  • sdfzyhx
  • 2016年07月04日 09:36
  • 133

ACdream 1429 Rectangular Polygon

动规
  • SenyeLicone
  • SenyeLicone
  • 2016年10月09日 23:57
  • 176

gdut Problem G: 等凹数字 (数位dp)

Problem G: 等凹数字 Description 定义一种数字称为等凹数字,即从高位到地位,每一位的数字先非递增再非递减,不能全部数字一样,且该数是一个回文数,即从左读到右与...
  • johsnows
  • johsnows
  • 2017年03月27日 17:25
  • 764

2017广东工业大学程序设计竞赛决赛 Problem G: 等凹数字(回文+数位dp)

Problem G: 等凹数字 Description 定义一种数字称为等凹数字,即从高位到地位,每一位的数字先非递增再非递减,不能全部数字一样,且该数是一个回文数,即从左读到右与从右读到左是一样...
  • HHH_go_
  • HHH_go_
  • 2017年03月29日 18:27
  • 1052

Hdu 4057 Rescue the Rabbit (AC自动机+状态压缩dp) - 2011 ACM-ICPC Dalian Regional Contest Problem G

大连的现场赛啊,快过去一年了。赛后知道这题是“AC自动机”的题目后就决定要研究研究这个神秘的AC自动机,最近把它给研究了一下,就把这个题翻出来再做做。发现还不是简单的AC自动机,还结合了“状态压缩dp...
  • morgan_xww
  • morgan_xww
  • 2012年08月08日 16:00
  • 3536

poj 2836 Rectangular Covering (状压dp)

n points are given on the Cartesian plane. Now you have to use some rectangles whose sides are paral...
  • ciel_s
  • ciel_s
  • 2017年04月04日 20:49
  • 98
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Problem G. Rectangular Polygon(dp + 转移重现)
举报原因:
原因补充:

(最多只允许输入30个字)