Problem 1287 : Stopped Watches

Problem C: Stopped Watches
http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/description.jsp?id=1287

  • 問題概要

ある島で火山が噴火して、人々全滅。
時計もそのときとまった。
その時計は文字盤もはげてしまってるし、どれが秒針か分針かとかがわからない。
どちらが上かもわからない。
任意の場所を基準に、そこからの円を60分割したうちの何個目をさしているかあたえられる。
それは、それらの時計が示す時間が、回転させたり、どれをどの針とするかによって、
複数あることを示している。
噴火によってとまったはずなので、その時間差はとても小さいはずである。
時計が示す時間をすべて含む一番小さい範囲の、その範囲の最初の最後を求めよ。

  • 解法

すべての時間の候補をあげて、すべての時計の候補を含む範囲をもとめる。
この問題の時計は、12分ごとに短針も動くので、短針の位置から分針に矛盾がないか調べる必要がある。
時間にどの時計からの候補なのかのidを持たせる必要がある。

  • ソース
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<sstream>
#include<cassert>
#include<queue>
#include<stack>

#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define ALL(C)     (C).begin(),(C).end()
#define pb         push_back
#define mp         make_pair
#define vint       vector<int>
#define FOR(it,o)  for(__typeof((o).begin()) it=(o).begin(); it!=(o).end(); ++it)
#define lli	    long long int
#define ld	    long double

using namespace std;

class Time{
public:
  int h, m, s, id;
  bool valid(){
    int tmp = h%5;
    return (tmp * 12 <= m && (tmp+1) * 12 > m);
  }
  void next(){
    s++;
    m++;
    h++;
    s%=60;
    m%=60;
    h%=60;
  }
  void output(){
    printf("%02d:%02d:%02d", h/5, m, s);
  }
  bool operator < (const Time &t) const{
    if( h/5 != t.h/5)return h/5 < t.h/5;
    if( m != t.m)return m < t.m;
    if( s != t.s)return s < t.s;
    return false;
  }
};

int dif(Time t2, Time t1){
  int sum = 0;
  sum += t1.h /5 * 60 * 60;
  sum += t1.m * 60;
  sum += t1.s;
  sum -= t2.h  /5 * 60 * 60;
  sum -= t2.m * 60;
  sum -= t2.s;
  if(sum < 0){
    t1.output();
    t2.output();
  }
  return sum;
}

main(){
  
  int n;
  while(cin >> n){
    if(n == 0)break;
    vector<Time> v;
    rep(i, n){
      Time t;
      t.id = i;
      int num[3];
      rep(j, 3)cin >> num[j];
      sort(num, num + 3);
      do{
	t.h = num[0];
	t.m = num[1];
	t.s = num[2];
	rep(j, 60){
	  if(t.valid())v.pb(t);
	  t.next();
	}
      }while(next_permutation(num, num + 3));
    }
    sort(ALL(v));
    int mini = 100000000;
    Time ans[2];
    for(int i=0; i<v.size(); i++){
      bool used[n];
      rep(j, n)used[j] = false;
      used[v[i].id] = true;
      for(int j = i+1; j<v.size(); j++){
	used[v[j].id] = true;
	bool find = false;
	rep(k, n){
	  if(!used[k])find = true;
	}
	if(!find){
	  if(mini > dif(v[i], v[j])){
	    mini = dif(v[i], v[j]);
	    ans[0] = v[i];
	    ans[1] = v[j];
	  }
	  break;
	}
      }
    }
    ans[0].output();
    cout << ' ';
    ans[1].output();
    cout << endl;
  }
}

楽しかったー。時間っていろいろややこしくてつかれた。。。
でも、たのしかったー。