1. 程式人生 > >topcoder srm 738 div1 FindThePerfectTriangle(枚舉)

topcoder srm 738 div1 FindThePerfectTriangle(枚舉)

desc cond 問題 pub ack info win continue multiple

Problem Statement

You are given the ints perimeter and area. Your task is to find a triangle with the following properties:

  • The coordinates of each vertex are integers between 0 and 3000, inclusive.
  • The perimeter of the triangle must be exactly perimeter, and its area must be exactly area
    .

If there are multiple solutions, you may choose any of them. Return a vector <int> with six elements: {x1, y1, x2, y2, x3, y3}, where (x1, y1), (x2, y2), and (x3, y3) are the coordinates of the vertices of your triangle. If there is no solution, return an empty vector <int> instead.

Definition

Class: FindThePerfectTriangle
Method: constructTriangle
Parameters: int, int
Returns: vector <int>
Method signature: vector <int> constructTriangle(int area, int perimeter)
(be sure your method is public)

Limits

Time limit (s): 2.000
Memory limit (MB): 256

Constraints

- area will be between 1 and 1,000,000, inclusive.
- perimeter will be between 1 and 1000, inclusive.

Examples

0)
6
11
Returns: { }
There are no valid triangles with area 6 and perimeter 11.
1)
6
12
Returns: {1, 1, 1, 4, 5, 4 }
The example output describes a right triangle with vertices at (1, 1), (1, 4) and (5, 4). Its sides have lengths 3, 4, and 5, hence its perimeter is 12. The area of the triangle is (3*4)/2 = 6.
2)
37128
882
Returns: {137, 137, 273, 410, 1, 410 }
3)
12
18
Returns: {1, 1, 4, 5, 1, 9 }
In this test case our solution constructed an isosceles triangle with vertices at (1, 1), (4, 5) and (1, 9).
4)
18096
928
Returns: {1, 1, 1, 88, 417, 88 }
5)
1000000
1000
Returns: { }

This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited. (c)2003, TopCoder, Inc. All rights reserved.

題意 給出三角形的面積和周長,找到三個坐標為整數的點,使得以它們為頂點的三角形符合條件,並滿足$$$1\le x_i\le 3000, 1\le y_i\le 3000, (i=1,2,3)$$$ 分析 假設三條邊的長度從大到小依次為$$$a, b, c$$$,通過枚舉$$$a$$$和$$$b$$$,可以找到所有面積大小正確的組合。接下來的問題就是如何把這樣的三角形放到網格上面。首先,$$$a^2$$$,$$$b^2$$$,$$$c^2$$$必須拆成兩個平方數的和,因為周長≤$$$1000$$$,所以$$$a,b,c\lt 1000$$$,只需要對$$$1^2, 2^2,...,1000^2$$$進行預處理,記錄它們所有拆成平方數的和的形式。對於一組$$$a, b, c$$$,遍歷$$$a$$$和$$$b$$$的拆分方式的組合,假設把$$$a$$$這條邊放到($$$0$$$,$$$0$$$)-($$$x_1$$$,$$$y_1$$$),$$$b$$$這條邊放到($$$0$$$,$$$0$$$)-($$$x_2$$$, $$$y_2$$$),那麽如果滿足$$$c^2=(x_1-x_2)^2+(y_1-y_2)^2$$$,就找到了一組坐標。然後只需要把坐標平移到規定的區域內就行了。我選擇的是所有坐標平移$$$x+1500,y+1500$$$ 總結 第一場topcoder,從將近1點打到2點,熬夜場永遠思路不清晰,暴力題都敲不出來(代碼該怎麽貼呀) 代碼
#include<bits/stdc++.h>
using namespace std;
vector<pair<int, int>> cnt[1000006];
class FindThePerfectTriangle
{
    public:
    vector <int> constructTriangle(int area, int perimeter) {
        int  c;
        for (int i = 1; i <= 1000; ++i)cnt[i*i].emplace_back(i, 0);
        for (int i = 1; i <= 1000; ++i) {
            for (int j = 1; j<i&&j*j+i*i<=1000000; ++j) {
                if (cnt[i*i + j*j].empty())continue;
                cnt[i*i + j*j].emplace_back(i, j);
            }
        }
        for (int a = 1; a <= 1000 && a + 1 < perimeter; a++) {
            for (int b = 1; b <= 1000 && a + b < perimeter&&b <= a; b++) {
                c = perimeter - a - b;
                if (a < c || b < c || a >= (b + c))continue;
                //用海拉公式的變形來驗證面積正確
                long long p = perimeter;
                long long s = p*(p - 2 * a)*(p - 2 * b)*(p - 2 * c);
                if (s == (long long)(16) * area*area) {
                    int A = a*a, B = b*b;
                    //枚舉A和B的拆分方式
                    for (int i = 0; i<cnt[A].size(); i++) 
                        for (int j = 0; j<cnt[B].size(); j++) {
                            int x1 = cnt[A][i].first, y1 = cnt[A][i].second;
                            int x2 = cnt[B][j].first, y2 = cnt[B][j].second;
                            int xx, yy;
                            for(int s1=-1;s1<=1;s1+=2)
                                for(int s2=-1;s2<=1;s2+=2){
                                    xx = x1 - s1*x2;
                                    yy = y1 - s2*y2;
                                    if(xx*xx+yy*yy==c*c){
                                        vector<int>res;
                                        res.push_back(1500); res.push_back(1500);
                                        res.push_back(1500+x1); res.push_back(1500+y1);
                                        res.push_back(1500+s1*x2); res.push_back(1500+s2*y2);
                                        return res;
                                    }
                                    xx = x1 - s1*y2;
                                    yy = y1 - s2*x2;
                                    if (xx*xx + yy*yy == c*c){
                                        vector<int>res;
                                        res.push_back(1500); res.push_back(1500);
                                        res.push_back(1500 + x1); res.push_back(1500 + y1);
                                        res.push_back(1500 + s1*y2); res.push_back(1500 + s2*x2);
                                        return res;
                                    }
                                }    
                        }
                    
                }
            }
        }
        vector<int>res;
        return res;
    }
};

topcoder srm 738 div1 FindThePerfectTriangle(枚舉)