zoukankan      html  css  js  c++  java
  • POJ 1971 Parallelogram Counting

    题目链接:

    http://poj.org/problem?id=1971

    题意:

    二维空间给n个任意三点不共线的坐标,问这些点能够组成多少个不同的平行四边形。

    题解:

    使用的平行四边形的判断条件:对角线互相平分的四边形是平行四边形。

    所以我们枚举每一条线段,如果有两条线段的中点是重合的,那么这四个顶点就能构成一个平行四边形,也就是说每条线段我们只要维护中点就可以了。

    1、map维护中点:(数据比较大,t了)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<map>
     6 #include<utility>
     7 using namespace std;
     8 typedef long long LL;
     9 
    10 const int maxn = 1111;
    11 
    12 int n;
    13 int x[maxn],y[maxn];
    14 map<pair<int,int>,int> mp;
    15 
    16 void init(){
    17     mp.clear();
    18 }
    19 
    20 int main(){
    21     int tc;
    22     scanf("%d",&tc);
    23     while(tc--){
    24         init();
    25         scanf("%d",&n);
    26         for(int i=0;i<n;i++){
    27             scanf("%d%d",x+i,y+i);
    28         }
    29         int ans=0;
    30         for(int i=0;i<n;i++){
    31             for(int j=i+1;j<n;j++){
    32                 ans+=mp[make_pair(x[i]+x[j],y[i]+y[j])];
    33                 mp[make_pair(x[i]+x[j],y[i]+y[j])]++;
    34             }
    35         }
    36         printf("%d
    ",ans);
    37     }
    38     return 0;
    39 }

    2、用hash做(vector来建表)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<map>
     6 #include<utility>
     7 #include<vector>
     8 using namespace std;
     9 typedef long long LL;
    10 
    11 const int maxn = 1111;
    12 //可能是因为vector<int> tab[mod]的初始化影响很大
    13 //1e3+7跑2985MS 1e4+7跑1282MS 1e5+7跑1750MS 1e6+7跑4532MS 
    14 const int mod = 1e3+7;
    15 
    16 struct Point {
    17     int x, y, cnt;
    18     Point(int x, int y, int cnt = 0) :x(x), y(y), cnt(cnt) {}
    19     Point() { cnt = 0; }
    20 }pt[maxn];
    21 
    22 int n;
    23 vector<Point> tab[mod];
    24 int Hash(const Point& p) {
    25     //LL tmp = (p.x) *1000000007 + p.y; 
    26     int tmp = ((p.x << 2) + (p.x >> 4)) ^ (p.y << 10); //折叠法,比上面一个稍微快一点
    27     //注意哈希出来的要是非负数
    28     tmp = (tmp%mod + mod) % mod;
    29     return tmp;
    30 }
    31 
    32 int add(const Point& p) {
    33     int key = Hash(p);
    34     int pos = -1;
    35     for (int i = 0; i<tab[key].size(); i++) {
    36         Point& tmp = tab[key][i];
    37         if (p.x == tmp.x&&p.y == tmp.y) {
    38             pos = i; break;
    39         }
    40     }
    41     int ret = 0;
    42     if (pos == -1) {
    43         tab[key].push_back(Point(p.x, p.y, 1));
    44     }
    45     else {
    46         ret = tab[key][pos].cnt;
    47         tab[key][pos].cnt++;
    48     }
    49     return ret;
    50 }
    51 
    52 void init() {
    53     for (int i = 0; i<mod; i++) tab[i].clear();
    54 }
    55 
    56 int main() {
    57     int tc;
    58     scanf("%d", &tc);
    59     while (tc--) {
    60         init();
    61         scanf("%d", &n);
    62         for (int i = 0; i<n; i++) {
    63             scanf("%d%d", &pt[i].x, &pt[i].y);
    64         }
    65         int ans = 0;
    66         for (int i = 0; i<n; i++) {
    67             for (int j = i + 1; j<n; j++) {
    68                 Point p = Point(pt[i].x + pt[j].x, pt[i].y + pt[j].y);
    69                 ans += add(p);
    70             }
    71         }
    72         printf("%d
    ", ans);
    73     }
    74     return 0;
    75 }

    3、用邻接表做散列表,初始化可以省一些时间 954MS

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<map>
     6 #include<utility>
     7 #include<vector>
     8 using namespace std;
     9 typedef long long LL;
    10 
    11 const int maxn = 1111;
    12 
    13 const int mod = 1e6+7;
    14 
    15 struct Point {
    16     int x, y, cnt, ne;
    17     Point(int x, int y, int cnt = 0) :x(x), y(y), cnt(cnt) {}
    18     Point(int x, int y, int cnt, int ne) :x(x), y(y), cnt(cnt), ne(ne) { }
    19     Point() { cnt = 0; }
    20 }pt[maxn],egs[maxn*maxn];
    21 
    22 int n;
    23 int tab[mod],tot;
    24 int Hash(const Point& p) {
    25     LL tmp = (p.x) *1000000007 + p.y; 
    26 //    int tmp = ((p.x << 2) + (p.x >> 4)) ^ (p.y << 10); //折叠法,比上面一个稍微快一点
    27     //注意哈希出来的要是非负数
    28     tmp = (tmp%mod + mod) % mod;
    29     return tmp;
    30 }
    31 
    32 int add(const Point& p) {
    33     int key = Hash(p);
    34     int pos = -1,_p=tab[key];
    35     while (_p != -1) {
    36         Point& e = egs[_p];
    37         if (p.x == e.x&&p.y == e.y) {
    38             pos = _p; break;
    39         }
    40         _p = e.ne;
    41     }
    42     int ret = 0;
    43     if (pos == -1) {
    44         egs[tot] = Point(p.x, p.y, 1, tab[key]);
    45         tab[key] = tot++;
    46     }
    47     else {
    48         ret = egs[pos].cnt;
    49         egs[pos].cnt++;
    50     }
    51     return ret;
    52 }
    53 
    54 void init() {
    55     memset(tab, -1, sizeof(tab));
    56     tot = 0;
    57 }
    58 
    59 int main() {
    60     int tc;
    61     scanf("%d", &tc);
    62     while (tc--) {
    63         init();
    64         scanf("%d", &n);
    65         for (int i = 0; i<n; i++) {
    66             scanf("%d%d", &pt[i].x, &pt[i].y);
    67         }
    68         int ans = 0;
    69         for (int i = 0; i<n; i++) {
    70             for (int j = i + 1; j<n; j++) {
    71                 Point p = Point(pt[i].x + pt[j].x, pt[i].y + pt[j].y);
    72                 ans += add(p);
    73             }
    74         }
    75         printf("%d
    ", ans);
    76     }
    77     return 0;
    78 }
  • 相关阅读:
    如何查看微信公众号的历史文章(微信订阅号查看历史消息)
    微信服务号有福啦 每月可以微信群发4次
    欲提高微信图文转化率 需学点如何吊胃口
    只需按一下空格键就可以标注 不用众里寻他千百度
    如何让你的微信图文转化率达到300%
    是智能手机推动windows xp系统停止服务吗
    响应式js幻灯片代码一枚
    微信公众平台回复链接可以直接访问,但不能是锚文字链接<a>标签
    如何用腾讯电脑管家备份微信聊天记录
    android版微信5.2.1更新 支持微信聊天记录备份到电脑上
  • 原文地址:https://www.cnblogs.com/fenice/p/5449935.html
Copyright © 2011-2022 走看看