2017-2018 ACM-ICPC, Asia Tsukuba Regional Contest B - Parallel Lines

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lifelikes/article/details/83185097

PS: 这是一道签到题, RB强者 恐怖如斯。
——————————————————
update: 其实就是一个暴搜题,我们脑残了 写成了DP 心态蹦了

Given an even number of distinct planar points, consider coupling all of the points into pairs. All the possible couplings are to be considered as long as all the given points are coupled to one and only one other point.

When lines are drawn connecting the two points of all the coupled point pairs, some of the drawn lines can be parallel to some others. Your task is to find the maximum number of parallel line pairs considering all the possible couplings of the points.

For the case given in the first sample input with four points, there are three patterns of point couplings as shown in Figure B.1. The numbers of parallel line pairs are 0, 0, and 1, from the left. So the maximum is 1.

Figure B.1. All three possible couplings for Sample Input 1

For the case given in the second sample input with eight points, the points can be coupled as shown in Figure B.2. With such a point pairing, all four lines are parallel to one another. In other words, the six line pairs (L1,L2)(L1,L2)

, (L1,L3)(L1,L3)

, (L1,L4)(L1,L4)

, (L2,L3)(L2,L3)

, (L2,L4)(L2,L4)

and (L3,L4)(L3,L4)

are parallel. So the maximum number of parallel line pairs, in this case, is 6. The input consists of a single test case of the following format. Inputmm

x1x1

y1y1


xmxm

ymym

 Figure B.2. Maximizing the number of parallel line pairs for Sample Input 2 The first line contains an even integer mm

, which is the number of points (2≤m≤162≤m≤16

). Each of the following mm

lines gives the coordinates of a point. Integers xixi

and yiyi

(−1000≤xi≤1000,−1000≤yi≤1000−1000≤xi≤1000,−1000≤yi≤1000

) in the ii

-th line of them give the xx

  • and yy

-coordinates, respectively, of the ii

-th point. The positions of points are all different, that is, xi≠xjxi≠xj

or yi≠yjyi≠yj

holds for all i≠ji≠j

. Furthermore, No three points lie on a single line. Output Output the maximum possible number of parallel line pairs stated above, in one line. Sample Input 14
0 0
1 1
0 2
2 4
Sample Output 11
Sample Input 28
0 0
0 5
2 2
2 7
3 -2
5 0
4 -2
8 2
Sample Output 26
Sample Input 36
0 0
0 5
3 -2
3 5
5 0
5 7
Sample Output 33
Sample Input 42
-1000 1000
1000 -1000
Sample Output 40
Sample Input 516
327 449
-509 761
-553 515
360 948
147 877
-694 468
241 320
463 -753
-206 -991
473 -738
-156 -916
-215 54
-112 -476
-452 780
-18 -335
-146 77
Sample Output 512

题意:
给出n个点 要将这些点两两配对构成线段,使得互相平行的线段数X最多
输出X*(X-1)/2

解题思路:
最多16个点,很容易想到枚举和状压。
斜率的种类是O(m^2)级别的。
考虑枚举斜率。
设dp[i] 表示i这种状态 组成同一种斜率的最大价值是多少。很显然,这是个背包DP。
复杂度也很好估计 最多合法的情况是C(2,16)+C(4,16)+C(6,16)+…+C(16,16); 这是是O(2^m)的。
所以DP复杂度是O(22*m ) 预处理复杂度是O((2m *(m3)) 感觉很棒。
日本签到题,恐怖如斯。

#include <bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define MP make_pair
#define lowbit(x) x&-x
#define clr(a) memset(a,0,sizeof(a))
#define _INF(a) memset(a,0x3f,sizeof(a))
#define FIN freopen("in.txt","r",stdin)
#define IOS ios::sync_with_stdio(false)
#define fuck(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int>pii;
typedef pair<ll, ll>pll;
typedef pair<double, int> pdi;
const int MAX = 20;
int m;
class Node{
public:
    int x,y;
};
bool vis[MAX];
int check(int x,int y,vector<Node> &node){
    int ans =0;
    memset(vis,0,sizeof vis);
    for(int i=0;i<node.size();i++){
        if(vis[i]) continue;
        int j=i+1;
        while(j<node.size()){
            if(vis[j]){
                j++;
                continue;
            }
            if(y*(node[i].x-node[j].x)==x*(node[i].y-node[j].y)){
                vis[j]=1;
                ans++;
                break;
            }
            j++;
        }
    }
    return ans;
}
Node node[MAX];
int check(int S){
    vector<Node> X;
    vector<Node> V;
    for(int i=0;i<m;i++){
        if((1<<i) & S){
            X.push_back(node[i]);
        }
    }
    for(int i=0;i<X.size();i++){
        for(int j=i+1;j<X.size();j++){
            Node cnt;
            cnt.x = X[i].x-X[j].x;
            cnt.y = X[i].y-X[j].y;
            V.push_back(cnt);
        }
    }
    int ans = 0;
    for(int i=0;i<V.size();i++){
        ans = max(ans,check(V[i].x,V[i].y,X));
    }
    if(ans *2 == X.size()){
        //cout<<ans<<endl;
        return ans*(ans-1)/2;
    }else{
        return -1;
    }
}
int dp[(1<<16)+10];
int main(){
    scanf("%d",&m);
    for(int i=0;i<m;i++){
        scanf("%d %d",&node[i].x,&node[i].y);
    }
    vector<int> OP;
    for(int i=0;i<(1<<m);i++){
        int cnt = check(i);
        if(cnt!=-1){
            //cout<<"i:"<<i<<","<<cnt<<endl;
            dp[i]=cnt;
            OP.push_back(i);
        }
    }
    int ans = 0;
    for(int i=0;i<OP.size();i++){
        for(int S=(1<<m)-1;S>=0;S--){
            if(S&OP[i]) continue;
            dp[S|OP[i]]=max(dp[S|OP[i]],dp[S]+dp[OP[i]]);
            ans = max(ans,dp[S|OP[i]]);
        }
    }
    cout<<ans<<endl;
}

猜你喜欢

转载自blog.csdn.net/lifelikes/article/details/83185097