SSブログ

AOJ 0237: Last Door [AOJ]

最近、問題解くのに時間かけすぎな気もしますが...

あんまりバシバシ解けるタイプでも無いので, そうなれるようにちょっとずつ変わって行きたい所存です.

ちなみにこれ解けてません. 三角関数まわりの誤差でしょうか.

強連結成分分解は間違ってないはずです.
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
 
#define MAX_N (128)
#define EPS (1e-5)
#define SQ(X) ((X) * (X))
#define EQ(a, b) (fabs(a - b) <= EPS)
#define D1 (-1)
#define D2 (1)
#define ONLINE (0)
 
using namespace std;
 
class Triangle {
    public:
        double x[3], y[3];
        int no;
};
 
class Point {
    public:
        double x, y;
         
        Point operator - (Point &a){
            Point ret;
            ret.x = x - a.x;
            ret.y = y - a.y;
            return (ret);
        }
};
 
vector<int> G[MAX_N];
vector<int> rG[MAX_N];
vector<int> compress[MAX_N];
vector<int> vs;
bool used[MAX_N];
bool group[MAX_N];
int cmp[MAX_N];
int N;
 
void addEdge(int from, int to)
{
    G[from].push_back(to);
    rG[to].push_back(from);
}
 
void dfs(int v)
{
    used[v] = true;
    for (int i = 0; i < G[v].size(); i++){
        if (!used[G[v][i]]){
            dfs(G[v][i]);
        }
    }
    vs.push_back(v);
}
 
void revDfs(int v, int k)
{
    used[v] = true;
    cmp[v] = k;
    for (int i = 0; i < rG[v].size(); i++){
        if (!used[rG[v][i]]){
            revDfs(rG[v][i], k);
        }
    }
}
 
int scc()
{
    int ret;
    memset(used, 0, sizeof(used));
    vs.clear();
     
    for (int i = 0; i < N; i++){
        if (!used[i]){
            dfs(i);
        }
    }
     
    memset(used, 0, sizeof(used));
     
    ret = 0;
    for (int i = vs.size() - 1; i >= 0; i--){
        if (!used[vs[i]]){
            revDfs(vs[i], ret++);
        }
    }
     
    for (int i = 0; i < N; i++){
        for (int j = 0; j < G[i].size(); j++){
            if (cmp[i] != cmp[G[i][j]]){
                compress[cmp[G[i][j]]].push_back(cmp[i]);
            }
        }
    }
     
    return (ret);
}
 
double inProduct(Point a, Point b)
{
    return (a.x * b.x + a.y * b.y);
}
 
double getSize(Point a)
{
    return (sqrt(SQ(a.x) + SQ(a.y)));
}
 
int checkCross(Point p1, Point p2, Point p3)
{
    Point vecA = p2 - p1, vecB = p3 - p1;
    double D = vecA.x * vecB.y - vecB.x * vecA.y;
    if (EQ(0, D)){
        return (ONLINE);
    }
    else if (D > 0){
        return (D1);
    }
    return (D2);
}
 
void judgeAdj(Triangle a, Triangle b, double dist)
{
    double len;
    Point p[4];
     
    len = 0.0;
    for (int i = 0; i < 3; i++){
        for (int j = i + 1; j < 3; j++){
            if (len < SQ(a.x[i] - a.x[j]) + SQ(a.y[i] - a.y[j])){
                len = SQ(a.x[i] - a.x[j]) + SQ(a.y[i] - a.y[j]);
                p[0].x = a.x[i], p[0].y = a.y[i];
                p[1].x = a.x[j], p[1].y = a.y[j];
            }
        }
    }
    //printf("%lf %lf %lf %lf\n", p[0].x, p[0].y, p[1].x, p[1].y);
    Point e, sa;
     
    e.x = 0, e.y = 1;
    sa = p[0] - p[1];
    double theta = acos(inProduct(e, sa) / (getSize(e) * getSize(sa)));
    if (fabs(theta - M_PI) < EPS){
        theta = 0;
    }
    //printf("theta = %lf\n", theta);
     
    p[2].x = p[0].x + dist * cos(theta), p[2].y = p[0].y + dist * sin(theta);
    p[3].x = p[1].x + dist * cos(theta), p[3].y = p[1].y + dist * sin(theta);
     
    bool cross = false;
     
    for (int i = 0; i < 3; i++){
        bool judge = true;
        Point k;
        k.x = b.x[i], k.y = b.y[i];
        judge &= (checkCross(p[0], p[1], k) * checkCross(p[2], p[3], k) <= 0);
        judge &= (checkCross(p[0], p[2], k) * checkCross(p[1], p[3], k) <= 0);
        cross |= judge;
    }
     
    if (cross == true){
        //printf("hoge, %d, %d\n", a.no, b.no);
        addEdge(a.no, b.no);
    }
     
}
 
int main()
{
    int n, d;
    Triangle data[128];
     
    while (1){
         
        scanf("%d%d", &n, &d);
         
        N = n;
        if (n + d == 0){
            break;
        }
         
        for (int i = 0; i < n; i++){
            data[i].no = i;
            for (int j = 0; j < 3; j++){
                scanf("%lf%lf", &data[i].x[j], &data[i].y[j]);
            }
        }
         
        for (int i = 0; i < n; i++){
            G[i].clear();
            rG[i].clear();
            compress[i].clear();
        }
         
        for (int i = 0; i < n; i++){
            for (int j = 0; j < n; j++){
                if (i != j){
                    judgeAdj(data[i], data[j], d);
                }
            }
        }
         
        int k = scc();
         
        int ans = 0;
        memset(used, 0, sizeof(used));
         
        for (int i = 0; i < k; i++){
            if (compress[i].size() == 0){
                ans++;
            }
        }
         
        printf("%d\n", ans);
    }
     
    return (0);
}

nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

[JOI合宿]2009-Day2:Adv..AOJ 0243: Filling Ga.. ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。