2014ACM/ICPC亚洲区广州站 部分题解

【A】题意:有N个操作,一种是加入一对数,一种是删除一对数,另外一种是求,现在集合里面的所有数队和当前x,y的乘积之和的最大值!正解好像是动态凸包,但是这题暴力也是可以跑过去的。大概10000+ms。

【代码】

//
//Created by just_sort 2016/11/3
//Copyright (c) 2016 just_sort.All Rights Reserved
//

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int, LL> pp;
#define MP(x,y) make_pair(x,y)
const int maxn = 200005;
const int N = 2005;
const int M = 4005;
const double PI = acos(-1.0);
const double eps = 1e-10;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>order_set;
//head

struct node{
    LL x, y;
    int used;
    node(){}
    node(int x, int y, int used):x(x), y(y), used(used){}
}a[50010];

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        if(n == 0) break;
        int t;
        LL x, y;
        int cnt = 0;
        for(int i = 1; i <= n; i++){
            scanf("%d%lld%lld",&t,&x,&y);
            if(t == 1){
                a[++cnt] = node(x,y,1);
            }
            else if(t == -1){
                for(int i = 1; i <= cnt; i++){
                    if(a[i].x == x && a[i].y == y && a[i].used == 1){
                        a[i].used = 0;
                    }
                }
            }
            else{
                LL mx = -1e12;
                for(int i = 1; i <= cnt; i++){
                    if(a[i].used == 1){
                        mx = max(mx, x*a[i].x + y*a[i].y);
                    }
                }
                printf("%lld\n",mx);
            }
        }
    }
}

【B】给了n个点,要求出两个不想交的矩形,使得面积最大,坑点是注意小矩形包含在大矩形里面的面积直接是大矩形的面积,其他为大小矩形面积和!至于做法,就是暴力枚举2个矩形的对角线,剩下的就是合法性的判断了!

【代码】

//
//Created by just_sort 2016/11/3
//CopyRight (c) 2016 just_sort.All Rights Reserved
//

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int, LL> pp;
#define MP(x,y) make_pair(x,y)
const int maxn = 200005;
const int inf = 0x3f3f3f3f;
const int unf = -0x3f3f3f3f;
const int N = 2005;
const int M = 4005;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>order_set;
//head

struct Point{
    int x, y;
    Point(){}
    Point(int x, int y):x(x),y(y){}
    void read(){
        scanf("%d%d",&x,&y);
    }
}A[33];

bool vis[222][222];
int Left, Right, up, down;
int n;

bool Isonline(Point a, Point b)
{
    return a.x==b.x || a.y==b.y;
}

bool Islegal(Point a)
{
    if(a.x >= Left && a.x <= Right && a.y >= down && a.y <= up) return 0;
    return 1;
}

bool Isin(Point a)
{
    return (a.x > Left && a.x < Right && a.y > down && a.y < up);
}

int getArea(Point a, Point b, Point &c, Point &d)
{
    if(a.x > b.x) swap(a, b);
    c = Point(a.x, b.y);
    d = Point(b.x, a.y);
    if(vis[c.x][c.y] && vis[d.x][d.y]) return abs(a.x-b.x)*abs(a.y-b.y);
    return unf;
}

int main()
{
    int n;
    while(scanf("%d",&n))
    {
        if(n == 0) break;
        memset(vis, false, sizeof(vis));
        for(int i = 1; i <= n; i++){
            A[i].read();
            vis[A[i].x][A[i].y] = 1;
        }
        //mei ju 1
        int ans = unf;
        Point C,D;
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                if(Isonline(A[i],A[j])) continue;
                int curarea1 = getArea(A[i],A[j],C,D);
                if(curarea1 == unf) continue;
                Left = min(A[i].x,A[j].x);
                Right = max(A[i].x,A[j].x);
                down = min(A[i].y, A[j].y);
                up = max(A[i].y,A[j].y);
                //mei ju 2
                for(int k = 1; k <= n; k++){
                    for(int l = 1; l <= n; l++){
                        if(Isonline(A[k],A[l])) continue;
                        int curarea2 = getArea(A[k],A[l],C,D);
                        if(curarea2 == unf || curarea2 > curarea1) continue;
                        if(Isin(A[k])&&Isin(A[l])&&Isin(C)&&Isin(D)){
                            //cout<<curarea1<<endl;
                            ans = max(curarea1,ans);
                        }
                        if(!Islegal(A[k])||!Islegal(A[l])||!Islegal(C)||!Islegal(D)) continue;
                        ans = max(ans, curarea1 + curarea2);
                        //cout<<curarea1+curarea2<<endl;
                    }
                }
            }
        }
        if(ans == unf){
            printf("imp\n");
        }
        else{
            printf("%d\n",ans);
        }
    }
}

【D】求圆和多面行的面积交!

【代码】

//
//Created by just_sort 2016/11/3
//Copyright (c) 2016 just_sort.All Rights Reserved
//

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int, LL> pp;
#define MP(x,y) make_pair(x,y)
const int maxn = 200005;
const int N = 2005;
const int M = 4005;
const double PI = acos(-1.0);
const double eps = 1e-8;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>order_set;
//head

struct point{
    double x, y;
    point(){}
    void read(){
        scanf("%lf%lf",&x,&y);
    }
    point(double x,double y):x(x),y(y){}
    friend point operator-(const point &a, const point &b){
        return point(a.x-b.x, a.y-b.y);
    }
    friend point operator*(const point &a, const point &b){
        return point(a.x*b.x, a.y*b.y);
    }
    friend point operator/(const point &a, const point &b){
        return point(a.x/b.x,a.y/b.y);
    }
    friend point operator*(const point &a, const double &x){
        return point(a.x*x, a.y*x);
    }
    friend point operator/(const point &a, const double &x){
        return point(a.x/x, a.y/x);
    }
}A,B,res[1200];

int dcmp(double k){
    return k < -eps ? -1 : k > eps ? 1 : 0;
}
double dot(const point &a, const point &b){
    return a.x*b.x + a.y*b.y;
}
double cross(const point &a, const point &b){
    return a.x*b.y - a.y*b.x;
}
double abs(const point &o){
    return sqrt(dot(o, o));
}
point crosspt(const point &a, const point &b, const point &p, const point &q){
    double a1 = cross(b-a, p-a);
    double a2 = cross(b-a, q-a);
    return (p*a2-q*a1)/(a2-a1);
}
double r;
int n;
double mysqrt(double n){
    return sqrt(max(0.0, n));
}

void circle_cross_line(point a, point b, point o, double r, point ret[], int &num){
    double x0 = o.x, y0 = o.y;
    double x1 = a.x, y1 = a.y;
    double x2 = b.x, y2 = b.y;
    double dx = x2 - x1, dy = y2 - y1;
    double A = dx*dx + dy*dy;
    double B = 2*dx*(x1 - x0) + 2*dy*(y1 - y0);
    double C = (x1 - x0)*(x1 - x0) + (y1 - y0)*(y1 - y0) - r*r;
    double delta = B*B - 4*A*C;
    num = 0;
    if(dcmp(delta) >= 0){
        double t1 = (-B - mysqrt(delta)) / (2*A);
        double t2 = (-B + mysqrt(delta)) / (2*A);
        if(dcmp(t1 - 1) <= 0 && dcmp(t1) >= 0){
            ret[num++] = point(x1 + t1*dx, y1 + t1*dy);
        }
        if(dcmp(t2 - 1) <= 0 && dcmp(t2) >= 0){
            ret[num++] = point(x1 + t2*dx, y1 + t2*dy);
        }
    }
}

double sector_area(const point &a, const point &b){
    double theta = atan2(a.y, a.x) - atan2(b.y, b.x);
    while(theta <= 0) theta += 2*PI;
    while(theta > 2*PI)  theta -= 2*PI;
    theta = min(theta, 2*PI - theta);
    return r * r * theta / 2.0;
}

double calc(const point &a, const point &b){
    point p[2];
    int num = 0;
    int ina = dcmp(abs(a) - r) < 0;
    int inb = dcmp(abs(b) - r) < 0;
    if(ina){
        if(inb) return fabs(cross(a, b)) / 2.0;
        else{
            circle_cross_line(a, b, point(0, 0), r, p, num);
            return sector_area(b, p[0]) + fabs(cross(a, p[0])) / 2.0;
        }
    }
    else{
        if(inb){
            circle_cross_line(a, b, point(0, 0), r, p, num);
            return sector_area(p[0], a) + fabs(cross(p[0], b)) / 2.0;
        }
        else{
            circle_cross_line(a, b, point(0, 0), r, p, num);
            if(num == 2){
                return sector_area(a, p[0]) + sector_area(p[1], b) + fabs(cross(p[0], p[1])) / 2.0;
            }
            else{
                return sector_area(a, b);
            }
        }
    }
}

double area(){
    double ret = 0;
    for(int i = 0; i < n; i++){
        int sgn = dcmp(cross(res[i], res[i+1]));
        if(sgn != 0){
            ret += sgn*calc(res[i], res[i+1]);
        }
    }
    return ret;
}

int main()
{
    double k;
    int ks = 1;
    while(scanf("%d%lf",&n,&k)!=EOF)
    {
        for(int i = 0; i < n; i++){
            res[i].read();
        }
        scanf("%lf%lf",&A.x, &A.y);
        scanf("%lf%lf",&B.x, &B.y);
        double E = (2*B.x - 2*k*k*A.x) / fabs(k*k - 1.0);
        double F = (2*B.y - 2*k*k*A.y) / fabs(k*k - 1.0);
        double G = (k*k*A.x*A.x + k*k*A.y*A.y - B.x*B.x - B.y*B.y) / fabs(k*k - 1.0);
        double rx = E/2.0;
        double ry = F/2.0;
        r = sqrt(G + E*E / 4.0 + F*F / 4.0);
        for(int i = 0; i < n; i++){
            res[i].x -= rx;
            res[i].y -= ry;
        }
        res[n] = res[0];
        double ans = fabs(area());
        //printf("%.10f\n",0.2729710441-ans);
        printf("Case %d: %.10f\n",ks++,ans);
    }
}

【E】水题,结构体排序

【代码】

//
//Created by just_sort 2016/11/3
//Copyright (c) 2016 just_sort.All Rights Reserved
//

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int, LL> pp;
#define MP(x,y) make_pair(x,y)
const int maxn = 200005;
const int N = 2005;
const int M = 4005;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>order_set;
//head

struct node{
    string s;
    int sc;
    bool operator<(const node &rhs) const{
        if(sc == rhs.sc) return s < rhs.s;
        else return sc > rhs.sc;
    }
}a[210];

int main()
{
    int n, m;
    while(scanf("%d",&n))
    {
        if(n == 0) break;
        for(int i = 1; i <= n; i++)
        {
            cin>>a[i].s>>a[i].sc;
        }
        sort(a+1, a+1+n);
        for(int i = 1; i <= n; i++){
            cout<<a[i].s<<" "<<a[i].sc<<endl;
        }
        scanf("%d",&m);
        for(int i = 1; i <= m; i++){
            string op;
            cin>>op;
            int pos=-1;
            for(int i = 1; i <= n; i++){
                if(a[i].s == op){
                    pos = i;
                    break;
                }
            }
            int x = 0;
            int cnt = 0;
            for(int i = pos; i >= 1; i--){
                if(a[i].sc == a[pos].sc){
                    cnt++;
                    x = i;
                }
                else break;
            }
            if(cnt==1){
                printf("%d\n",pos);
            }
            else{
                printf("%d %d\n",x,cnt);
            }
        }
    }
}


【I】给出n根木棍,随意组成几个三角形,问组合的面积最大是多少。贪心,从小到大排序之后贪心计算即可!

【代码】

#include<bits/stdc++.h>
using namespace std;
const int N =20;
double a[N];
double s(double x,double y,double z)
{
    double p=(x+y+z)/2;
    return sqrt(p*(p-x)*(p-y)*(p-z));
}
int main()
{
    int n;
    while(~scanf("%d",&n)&&n){
        for(int i=1;i<=n;i++) scanf("%lf",&a[i]);
        sort(a+1,a+1+n);
        double ans=0;
        for(int i=n;i>=3;){
            double x=a[i-2],y=a[i-1],z=a[i];
            if(x+y<=z){
                i--;
                continue;
            }
            else{
                ans+=s(x,y,z);
                i-=3;
            }
        }
        printf("%.2f\n",ans);
    }
    return 0;
}

【H】删一个点然后求最短路!暴力枚举这个点,然后最短路算法即可。注意重边!

【代码】

//
//Created by just_sort 2016/11/3
//Copyright (c) 2016 just_sort.All Rights Reserved
//

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
using namespace __gnu_pbds;
typedef long long LL;
typedef pair<int, LL> pp;
#define MP(x,y) make_pair(x,y)
const int maxn = 200005;
const int inf = 0x3f3f3f3f;
const int N = 2005;
const int M = 4005;
typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>order_set;
//head

int maze[33][33];
int dis[33];
int vis[33];
int n, m, Max;

int dij(int dian)
{
    for(int i = 1; i <= n; i++){
        vis[i] = 0;
        dis[i] = inf;
    }
    dis[1] = 0;
    //vis[1] = 1;
    vis[dian] = 1;
    for(int i = 1; i <= n; i++){
        int minn = inf, mark = -1;
        for(int j = 1; j <= n; j++){
            if(minn >= dis[j] && !vis[j]){
                minn = dis[j];
                mark = j;
            }
        }
        if(minn == inf) break;
        vis[mark] = 1;
        for(int j = 1; j <= n; j++){
            if(!vis[j] && dis[j] > dis[mark] + maze[mark][j]){
                dis[j] = dis[mark] + maze[mark][j];
            }
        }
    }
    return dis[n];
}

int main()
{
    while(scanf("%d%d",&n,&m))
    {
        if(n == 0 && m == 0) break;
        memset(vis,0,sizeof(vis));
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                maze[i][j] = maze[j][i] = inf;
            }
        }
        memset(dis,0,sizeof(dis));
        Max = -1;
        for(int i = 1; i <= m; i++)
        {
            int u, v, w;
            scanf("%d%d%d",&u,&v,&w);
            if(maze[u][v] == inf) maze[u][v] = maze[v][u] = w;
            else{
                if(maze[u][v]<w){
                    maze[u][v] = maze[v][u] = w;
                }
            }
        }

        bool ok = 1;
        for(int i = 2; i <= n-1; i++){
            int d = dij(i);
            if(d == inf){
                ok = 0;
                break;
            }
            else{
                Max = max(Max,dis[n]);
            }
        }
        if(ok == 0)
        {
            printf("Inf\n");
        }
        else{
            printf("%d\n",Max);
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值