AOJ 1139: Earth Observation with a Mobile Robot Team

この記事は、AOJ-ICPC Advent Calendarの記事です。


古い問題らしい癖問。
妙にやりにくい幾何パート、妙にやりにくいグラフパート、そしてそれらに劣らないほどのやりにくさを誇る入力形式。
無駄に大変だけどなんとかはなった。言われたとおりに実装すれば時間制限は全然問題ない。

本当に書きにくい問題だったけどコンパイルを通してから直接1発ACが取れてしまった。
さすがに幾何実装の
http://pbs.twimg.com/media/CT1mUZgVAAI5l17.jpg
って感じがした。

#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<string>
#include<queue>
using namespace std;
const double EPS = 1e-10;
const double INF = 1e+10;
const double PI = acos(-1);

char in[100];
string name[110];
vector<Pt>v[110];
vector<double>t[110];
vector<pair<double,pair<int,int> > >ev;
vector<string>ans;
int ret[110];
int g[110][110];
int bfs[110];
int main(){
    int a,b,c;
    scanf("%d%d%d",&a,&b,&c);
    scanf("%s",in);
    int na,nb,nc;
    while(a){
        double r=(double)c;
        for(int i=0;i<110;i++){
            v[i].clear();
            t[i].clear();
        }
        for(int i=0;i<a;i++){
            name[i]=in;
            while(1){
                int chk=scanf("%s",in);
                if(chk==-1)break;
                if('a'<=in[0]&&in[0]<='z')break;
                int tmp,x,y;
                sscanf(in,"%d",&tmp);
                na=tmp;
                t[i].push_back((double)tmp);
                scanf("%d%d",&x,&y);
                nb=x;nc=y;
                v[i].push_back(Pt((double)x,(double)y));
            }
            if(i==a-1){
                t[i].pop_back();
                v[i].pop_back();
            }
        }
        ev.clear();
        for(int i=0;i<a;i++)for(int j=i+1;j<a;j++){
            if((v[i][0]-v[j][0]).ABS()<r)ev.push_back(make_pair(0,make_pair(i,j)));
            int L=1;
            int R=1;
            Pt at=v[i][0]-v[j][0];
            while(1){
                double left=max(t[i][L-1],t[j][R-1]);
                double right=min(t[i][L],t[j][R]);
                Pt tv=v[i][L]-v[j][R];
                if(iCS(Pt(0,0),r,at,at+tv*(right-left))){
                    pair<Pt,Pt> it=pCL(Pt(0,0),r,at,at+tv*(right-left));
                    if(iSP(at,it.first,at+tv*(right-left))==2||(at+tv*(right-left)-it.first).ABS()<EPS){
                        ev.push_back(make_pair(left+(it.first-at).ABS()/(tv.ABS()),make_pair(i,j)));
                    }
                    if(iSP(at,it.second,at+tv*(right-left))==2||(at+tv*(right-left)-it.second).ABS()<EPS){
                        ev.push_back(make_pair(left+(it.second-at).ABS()/(tv.ABS()),make_pair(i,j)));
                    }
                }
                at=at+tv*(right-left);
                if(L==t[i].size()-1&&R==t[j].size()-1)break;
                else if(L==t[i].size()-1)R++;
                else if(R==t[j].size()-1)L++;
                else if(t[i][L]>t[j][R]+EPS)R++;
                else if(t[i][L]+EPS<t[j][R])L++;
                else {L++;R++;}
            }
        }
        std::sort(ev.begin(),ev.end());
        for(int i=0;i<a;i++)ret[i]=0;
        ret[0]=1;
        for(int i=0;i<a;i++)for(int j=0;j<a;j++)g[i][j]=0;
        for(int i=0;i<ev.size();i++){
            g[ev[i].second.first][ev[i].second.second]^=1;
            if(g[ev[i].second.first][ev[i].second.second]&&ret[ev[i].second.first]+ret[ev[i].second.second]){
                queue<int>Q;
                for(int j=0;j<a;j++)bfs[j]=0;
                Q.push(ev[i].second.first);
                bfs[ev[i].second.first]=1;
                while(Q.size()){
                    int at=Q.front();
                    Q.pop();
                    for(int j=0;j<a;j++){
                        if(!bfs[j]&&(g[at][j]||g[j][at])){
                            bfs[j]=1;Q.push(j);
                        }
                    }
                }
                for(int j=0;j<a;j++)if(bfs[j])ret[j]=1;
            }
        }
        ans.clear();
        for(int i=0;i<a;i++)if(ret[i])ans.push_back(name[i]);
        std::sort(ans.begin(),ans.end());
        for(int i=0;i<ans.size();i++)printf("%s\n",ans[i].c_str());
        a=na;b=nb;c=nc;
    }
}