【问题标题】:finding maximum length of upper envolope [closed]找到上包络线的最大长度
【发布时间】:2014-08-17 17:44:13
【问题描述】:

我正在解决一个 spoj 问题 Rectangles Perimeter 问题是

给定 n 个矩形,编号从 1 到 n。我们将它们紧紧地放在轴 OX 上,从左到右,根据 矩形的数字。每个矩形都保持在轴 OX 上 较短或较长的一侧(见下图)。计算 上包络线的长度,即获得的周长 数字减去左、右和 图片的底部直线段。写程序到 求上包络线的最大可能长度。

例如

一种配置,产生上封套的最大长度 线,显示在图片上。 上包络线由 DC、CG、GF、FJ、JI、IM、 ML、LP 和 PO。 总长度为 5 + 6 + 3 + 7 + 10 + 13 + 7 + 12 + 5 = 68

输入是

在标准输入的第一行,n 的值是 书面。在接下来的 n 行中,每行给出两个整数—— a_i 和 b_i - 第 i 个矩形的边长。约束: 0

样本输入:

5 
2 5 
3 8 
1 10 
7 14 
2 5 

输出是

在标准输出的一行,你的程序应该写 结果为正整数

样本输出

68

我正在使用一种方法,我一个接一个地固定矩形并找到上包络线的最大长度,然后使用该 ans 来找到下一个最大包络线长度,依此类推..

我的代码是...

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <deque>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <string>
#include <vector>
#include <functional>
#include <numeric>
#include <utility>
#include<string.h>

using namespace std;

typedef double dbl;
typedef float flt;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<ll,int> pli;


#define eps 1e-9
#define inf 1000000000
#define infll 1000000000000000000LL
#define abs(x) ((x)<0?-(x):(x))
#define sqr(x) ((x)*(x))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define sz(x) ((int)(x).size())
#define FORab(i,a,b) for (int i=(a); i<=(b); ++i)
#define RFORab(i,a,b) for (int i=(a); i>=(b); --i)
#define FOR1(i,n) FORab(i,1,(n))
#define RFOR1(i,n) RFORab(i,(n),1)
#define FOR(i,n) FORab(i,0,(n)-1)
#define RFOR(i,n) RFORab(i,(n)-1,0)
#define allstl(i,x,t) for (t::iterator i = (x).begin(); i!=(x).end(); ++i)
#define rallstl(i,x,t) for (t::reverse_iterator i = (x).rbegin(); i!=(x).rend(); ++i)
#define ms(a,v) memset(a,v,sizeof(a))
#define msn(a,v,n) memset(a,v,n*sizeof(a[0]))
#define mcp(d,s,n) memcpy(d,s,n*sizeof(s[0]))

template<class T> inline void checkmin(T &a,T b){if(b<a) a=b;}
template<class T> inline void checkmax(T &a,T b){if(b>a) a=b;}

int main()
{
    int n;
    int e1=0,e2=0,e3=0;
    freopen("input.txt","r",stdin);
    cin>>n;
    FOR(i,n)
    {
        int l,b;
        cin>>b>>l;
        if(i==0)
        {
            e1=l;
            e2=b;
            e3=b;
           // cout<<e1<<"\n";
            continue;
        }
        int t1=e1+l+max(abs((b-e2)),abs((b-e3)));
        int t2=e1+b+max(abs((l-e2)),abs((l-e3)));
        if(t1<t2)
        {
            e1=t2;
            e2=l;
            e3=e2;
        }
        else if(t1==t2)
        {
            e1=t1;
            e2=l;
            e3=b;
        }
        else
        {
            e1=t1;
            e2=b;
            e3=e2;
        }
       // cout<<e1<<"\n";
    }
    cout<<e1<<"\n";
    return 0;
}

但我仍然得到一个错误的答案我不明白为什么我得到一个错误的答案..

【问题讨论】:

  • 这个问题需要一个导致失败的测试用例。
  • @DavidEisenstat 我的解决方案有什么问题..
  • 我不知道。在没有任何迹象表明存在真正问题的情况下浏览那么多未注释的代码是很多问题。
  • 为了使您的代码对其他人可读,您应该在没有宏的情况下编写它(即使是循环声明也使用宏)并使用方法。您还可以考虑更有意义的变量名称。
  • 好吧,如果你想让别人回答你的问题的可能性更大,那么你可以 (i) 删除无关代码 (ii) 更好地解释你的代码应该做什么 (iii ) 编写一个蛮力解决方案,编写一个小的随机示例生成器,并发布一个小测试用例,其中该代码和蛮力解决方案给出不同的输出。目前,这个问题可能会因 (i) 和 (iii) 解决的一系列问题而被搁置。

标签: c++ algorithm dynamic-programming


【解决方案1】:

你的答案很可能是因为贪心算法不正确(我说很可能只是因为我没有反例,我实际上确定它是不正确的)。

您可以改用动态编程。状态为(prefix_len, rotated),其中prefix_len 是已处理的矩形数量,rotated 是一个布尔值,指示最后一个矩形是否被旋转。每个状态的值是周长的最大长度。 基本情况是只有一个矩形的情况(很简单)。要计算其他状态的值,您可以从左到右迭代矩形,将它们置于旋转和未旋转位置,然后选择最佳选项:从状态 (prefix_len - 1, False)(prefix_len - 1, True) 进行转换,具体取决于哪个一个提供更长的周长。
答案是max(f(n, False), f(n, True))

此算法使用O(n) 时间和O(1) 内存(因为您实际上只需要存储prefix_len - 1 的值)。

【讨论】:

    【解决方案2】:

    当您从左向右传递时,您当前的算法当前似乎选择矩形i 的方向,该方向使矩形0 到i 的上包络长度最大化。但是看看这个例子。如果少一个矩形,那么最好的解决方案是让 HKLM 顺时针转动。因此,矩形的最佳方向不仅仅取决于其左侧的矩形;它还取决于其右侧的矩形。

    解决此问题的一种方法是通过动态规划。我们可以观察到,一个矩形的最佳方向实际上只取决于紧邻它的两个矩形,所以我们只需要保持一个恒定数量的状态。这是一些代码。

    // The upper envelope of rectangles 0 through i - 1 given that we orient i - 1 horizontally
    int envelopeHorizontal = 0;
    // The upper envelope or rectangles 0 through i - 1 given that we orient i - 1 vertically
    int envelopeVertical = 0;
    
    int numRectangles;
    std::cin >> numRectangles;
    
    int prevShortSide = 0, prevLongSide = 0;
    for (int i = 0; i < numRectangles; ++i) {
        int shortSide, longSide;
        std::cin >> shortSide >> longSide;
    
        if (i == 0) {
            envelopeHorizontal = longSide;
            envelopeVertical = shortSide;
        } else {
            const int newHorizontal = longSide
                + std::max(std::abs(prevLongSide - shortSide) + envelopeVertical,
                           std::abs(prevShortSide - shortSide) + envelopeHorizontal);
            const int newVertical = shortSide
                + std::max(std::abs(prevLongSide - longSide) + envelopeVertical,
                           std::abs(prevShortSide - longSide) + envelopeHorizontal);
            envelopeHorizontal = newHorizontal;
            envelopeVertical = newVertical;
        }
        prevShortSide = shortSide;
        prevLongSide = longSide;
    }
    std::cout << std::max(envelopeHorizontal, envelopeVertical) << "\n";
    

    PS 一旦你的代码运行起来,我强烈建议你将它提交给codereview.SE——你似乎已经养成了一些让你的代码很难理解的习惯。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多