Problem:
Problem C:Mobile Phone Coverage

A mobile phone company ACMICPC (Advanced Cellular, Mobile, and Internet-Connected Phone Corporation) is planning to set up a collection of antennas for mobile phones in a city called Maxnorm. The company ACMICPC has several collections for locations of antennas as their candidate plans, and now they want to know which collection is the best choice.

for this purpose, they want to develop a computer program to find the coverage of a collection of antenna locations. Each antenna Ai has power ri, corresponding to "radius". Usually, the coverage region of the antenna may be modeled as a disk centered at the location of the antenna (xi, yi) with radius ri. However, in this city Maxnorm such a coverage region becomes the square [xi − ri, xi + ri] × [yi − ri, yi + ri]. In other words, the distance between two points (xp, yp) and (xq, yq) is measured by the max norm max{ |xp − xq|, |yp − yq|}, or, the L∞ norm, in this city Maxnorm instead of the ordinary Euclidean norm √ {(xp − xq)2 + (yp − yq)2}.

As an example, consider the following collection of 3 antennas

4.0 4.0 3.0
5.0 6.0 3.0
5.5 4.5 1.0

depicted in the following figure

where the i-th row represents xi, yi ri such that (xi, yi) is the position of the i-th antenna and ri is its power. The area of regions of points covered by at least one antenna is 52.00 in this case.

Write a program that finds the area of coverage by a given collection of antenna locations.

Input

The input contains multiple data sets, each representing a collection of antenna locations. A data set is given in the following format.

n
x1 y1 r1
x2 y2 r2
. . .
xn yn rn

The first integer n is the number of antennas, such that 2 ≤ n ≤ 100. The coordinate of the i-th antenna is given by (xi, yi), and its power is ri. xi, yi and ri are fractional numbers between 0 and 200 inclusive.

The end of the input is indicated by a data set with 0 as the value of n.

Output

For each data set, your program should output its sequence number (1 for the first data set, 2 for the second, etc.) and the area of the coverage region. The area should be printed with two digits to the right of the decimal point, after rounding it to two decimal places.

The sequence number and the area should be printed on the same line with no spaces at the beginning and end of the line. The two numbers should be separated by a space.

Sample Input

3
4.0 4.0 3.0
5.0 6.0 3.0
5.5 4.5 1.0
2
3.0 3.0 3.0
1.5 1.5 1.0
0

Output for the Sample Input

1 52.00
2 36.00

Solution in JAVA (judge verdict: Accepted)

import java.util.*;
import static java.lang.Math.*;
public class Main {
	final Scanner sc=new Scanner(System.in);
	public static void main(String[] args) {
		new Main().doIt();
	}
	void doIt(){
		new AOJ1202();
	}
	
	class AOJ1202{
		AOJ1202(){
			int QNUM=1;
			while(true){
				int N=sc.nextInt();
				if(N==0)	break;
				TreeSet<Double> hx=new TreeSet<Double>(),hy=new TreeSet<Double>();
				ArrayList<Square> sq=new ArrayList<Square>();
				for(int i=0; i<N; i++){
					double x=sc.nextDouble(),y=sc.nextDouble(),d=sc.nextDouble();
					double lx=x-d,rx=x+d,by=y-d,uy=y+d;
					hx.add(lx);	hx.add(rx);	hy.add(by);	hy.add(uy);
					sq.add(new Square(lx,rx,by,uy));
				}
				ArrayList<Double> mx=new ArrayList<Double>(),my=new ArrayList<Double>();
				for(double d:hx)	mx.add(d);
				for(double d:hy)	my.add(d);
				boolean[][] b=new boolean[mx.size()][my.size()];
				for(Square s:sq){
					for(int x=0; x<mx.size(); x++){
						for(int y=0; y<my.size(); y++){
							if(s.lx<=mx.get(x) && mx.get(x)<s.rx && s.by<=my.get(y) && my.get(y)<s.uy)	b[x][y]=true;
						}
					}
				}
				double ans=0.0;
				for(int x=0; x+1<mx.size(); x++){
					for(int y=0; y+1<my.size(); y++){
						if(b[x][y])	ans+=abs((mx.get(x+1)-mx.get(x))*(my.get(y+1)-my.get(y)));
					}
				}
				System.out.printf("%d %.2f\n",(QNUM++),ans);
			}
		}
		class Square{
			double lx,rx,by,uy;
			Square(double lx,double rx,double by,double uy){this.lx=lx; this.rx=rx; this.by=by; this.uy=uy;}
		}
	}
	
	class AOJ1204{
		int N,INF=Integer.MAX_VALUE/4;
		int[] pl;
		AOJ1204(){
			while(true){
				N=sc.nextInt();
				if(N==0)	break;
				pl=new int[N];
				for(int u=0; u<=4; u++){
					String line=sc.next();
					for(int idx=0; idx<N; idx++){
						if(line.charAt(idx)=='X')	pl[idx]=u;
					}
				}
				boolean[][] map=new boolean[N*10+1][5];
				for(int i=0; i<N; i++)	map[i][pl[i]]=true;
				System.out.println(solve(map,0,1));
			}
		}
		int solve(boolean[][] map,int lidx,int depth){
			if(depth==10){
				return lidx+N;
			}
			int ret=INF;
			for(int offset=1; offset<=N; offset++){
				int idx=lidx+offset;
				if(idx+N>=ret)	break;
				boolean flag=true;
				int tmp=0;
				for(int i=0; i<N; i++){
					if(map[idx+i][pl[i]]){
						flag=false;
						tmp=i;
						break;
					}
					map[idx+i][pl[i]]=true;
				}
				if(flag)	ret=min(ret, solve(map,idx,depth+1));
				for(int i=0; i<(flag?N:tmp); i++)	map[idx+i][pl[i]]=false;
			}
			return ret;
		}
	}
	
	
	
	class AOJ1282{
		AOJ1282(){
			while(true){
				String s=sc.nextLine();
				
			}
		}
	}
	
	class AOJ1228{
		final int[] vx={0,1,1,0,-1,-1}, vy={-1,0,1,1,0,-1};
		final int OFFSET=100,MAX=210;
		AOJ1228(){
			final int N=sc.nextInt();
			sc.nextLine();
			for(int I=0; I<N; I++){
				String seq1=sc.nextLine(),seq2=sc.nextLine(),dammy=sc.nextLine();
				boolean[][] map1=new boolean[MAX][MAX];
				int x=OFFSET,y=OFFSET;
				map1[x][y]=true;
				for(char c:seq1.toCharArray()){
					int v=c-'a';
					x+=vx[v];	y+=vy[v];
					map1[x][y]=true;
				}
				map1=offset(map1);
				//debug
				//disp(map1,20);
				boolean ans=false;
				for(int rot=0; rot<6; rot++){
					x=OFFSET;	y=OFFSET;
					boolean[][] map2=new boolean[MAX][MAX];
					map2[x][y]=true;
					for(char c:seq2.toCharArray()){
						int v=(c-'a'+rot)%6;
						x+=vx[v];	y+=vy[v];
						//debug 
						//System.out.print("("+x+","+y+") ");
						map2[x][y]=true;
					}
					//debug
					//System.out.println();
					//disp(offset(map2),20);
					if(Arrays.deepEquals(map1, offset(map2))){
						ans=true;
						break;
					}
				}
				System.out.println(ans);
			}
		}
		
		boolean[][] offset(boolean[][] b){
			int xmin=MAX,ymin=MAX;
			for(int x=0; x<MAX; x++){
				for(int y=0; y<MAX; y++){
					if(b[x][y]){
						xmin=min(xmin,x);	ymin=min(ymin,y);
						break;
					}
				}
			}
			boolean[][] nb=new boolean[MAX][MAX];
			for(int x=xmin; x<MAX; x++){
				for(int y=ymin; y<MAX; y++)	nb[x-xmin][y-ymin]=b[x][y];
			}
			return nb;
		}
		void disp(boolean[][] b,int n){
			for(int y=0; y<n; y++){
				for(int x=0; x<n; x++)	System.out.print(b[x][y]?"#":".");
				System.out.println();
			}
			System.out.println("---------------");
		}
	}
	
	class AOJ1219{
		AOJ1219(){
			while(true){
				int N=sc.nextInt(),S=sc.nextInt();
				if(N==0 || S==0)	break;
				ArrayList<ArrayList<Integer>> guard=new ArrayList<ArrayList<Integer>>();
				int ans=0,remain=-1,now=-1;
				int[] idx=new int[N],r=new int[N];
				for(int i=0; i<N; i++){
					guard.add(new ArrayList<Integer>());
					while(true){
						int in=sc.nextInt();
						if(in==0)	break;
						guard.get(i).add(in);
					}
					r[i]=guard.get(i).get(0);
				}
				//System.out.println(guard);
				LinkedList<Integer> queue=new LinkedList<Integer>();
				for(int i=1; i<S; i++){
					for(int j=0; j<N; j++){
						if(idx[j]%2==0){	// 放電
							if(--r[j]<=0){
								idx[j]=(idx[j]+1)%guard.get(j).size();
								r[j]=guard.get(j).get(idx[j]);
								if(queue.isEmpty() && remain<=0){
									now=j;
									remain=r[j]+1;
								}else{
									queue.add(j);
								}
							}
						}
					}
					if(--remain==0){
						idx[now]=(idx[now]+1)%guard.get(now).size();
						r[now]=guard.get(now).get(idx[now]);
						if(!queue.isEmpty()){
							now=queue.poll();
							remain=r[now];
						}
					}
					ans+=queue.size();
//					System.out.println("AI"+i+" N"+now+" R"+remain+" "+queue.size());
//					System.out.println(Arrays.toString(r));
//					System.out.println(Arrays.toString(idx));
				}
				System.out.println(ans);
			}
		}
		class Guard{
			int[] c;
			
		}
	}
	
	class AOJ1218{
		final int INF=Integer.MAX_VALUE/4;
		final int[] vx={0,1,0,-1},vy={1,0,-1,0};
		int W,H;
		AOJ1218(){
			while(true){
				W=sc.nextInt();	H=sc.nextInt();
				if(W==0 || H==0)	break;
				int sx=-1,sy=-1,gx=-1,gy=-1,cx=-1,cy=-1;
				boolean[][] wall=new boolean[W][H];
				for(int y=0; y<H; y++){
					for(int x=0; x<W; x++){
						switch(sc.nextInt()){
						case 1:	wall[x][y]=true;	break;
						case 2:	cx=x; cy=y; break;
						case 3:	gx=x; gy=y; break;
						case 4:	sx=x; sy=y; break;
						}
					}
				}
				PriorityQueue<Pos> open=new PriorityQueue<Main.AOJ1218.Pos>();
				open.add(new Pos(sx,sy,cx,cy,0));
				int[][][][] closed=new int[W][H][W][H];
				for(int i=0; i<W; i++)for(int j=0; j<H; j++)for(int k=0; k<W; k++)for(int m=0; m<H; m++)closed[i][j][k][m]=INF;
				closed[sx][sy][cx][cy]=0;
				boolean flag=false;
				while(!open.isEmpty()){
					Pos now=open.poll();
					//System.out.println(now);
					for(int i=0; i<4; i++){
						int xx=now.x+vx[i],yy=now.y+vy[i];
						if(!isInRange(xx,yy))	continue;
						if(wall[xx][yy])	continue;
						if(xx==now.cx && yy==now.cy){
							int xxx=xx+vx[i],yyy=yy+vy[i];
							if(!isInRange(xxx,yyy))	continue;
							if(wall[xxx][yyy])	continue;
							if(closed[xx][yy][xxx][yyy]<=now.step+1)	continue;
							if(xxx==gx && yyy==gy){
								System.out.println(now.step+1);
								open.clear();
								flag=true;
								break;
							}
							open.add(new Pos(xx,yy,xxx,yyy,now.step+1));
							closed[xx][yy][xxx][yyy]=now.step+1;
						}else{
							if(closed[xx][yy][now.cx][now.cy]<=now.step)	continue;
							open.add(new Pos(xx,yy,now.cx,now.cy,now.step));
							closed[xx][yy][now.cx][now.cy]=now.step;
						}
					}
				}
				if(!flag)	System.out.println(-1);
			}
		}
		boolean isInRange(int x,int y){return 0<=x && x<W && 0<=y && y<H;}
		class Pos implements Comparable<Pos>{
			int x,y,cx,cy,step;
			Pos(int x,int y,int cx,int cy,int step){this.x=x; this.y=y; this.cx=cx; this.cy=cy; this.step=step;}
			@Override public int compareTo(Pos o) {
				if(this.step<o.step)	return -1;
				if(this.step>o.step)	return 1;
				return 0;
			}
			@Override public String toString(){return "("+x+","+y+") ("+cx+","+cy+") "+step;}
		}
	}
	
	// 0:55WA 1:20AC
	class AOJ1227{
		ArrayList<ArrayList<String>> dic,dic2ans;
		AOJ1227(){
			String s="22233344455566677778889999";
			char[] dic2=new char[26];
			for(int i=0; i<26; i++)	dic2[i]=s.charAt(i);
			while(true){
				int N=sc.nextInt();
				if(N==0)	break;
				dic=new ArrayList<ArrayList<String>>(10);
				dic2ans=new ArrayList<ArrayList<String>>(10);
				for(int i=0; i<10; i++){
					dic.add(new ArrayList<String>());
					dic2ans.add(new ArrayList<String>());
				}
				for(int i=0; i<N; i++){
					String in=sc.next();
					StringBuilder sb=new StringBuilder(in);
					for(int j=0; j<sb.length(); j++)	sb.setCharAt(j, dic2[sb.charAt(j)-'a']);
					int init=sb.charAt(0)-'0';
					dic.get(init).add(sb.toString());
					dic2ans.get(init).add(in);
				}
				//System.out.println(dic);
				//System.out.println(dic2ans);
				String in=sc.next();
				solve(in, 0, new String());
				System.out.println("--");
			}
		}
		void solve(String in,int idx,String ans){
			if(idx==in.length())	System.out.println(ans+".");
//			else if(idx>in.length()){
//				System.out.println("index out of");
//				System.out.println(idx+" "+ans);
//			}
			else{
				int init=in.charAt(idx)-'0';
				for(int i=0; i<dic.get(init).size(); i++){
					String s=dic.get(init).get(i);
					if(in.startsWith(s, idx))	solve(in, idx+s.length(), ans+(ans.length()==0?dic2ans.get(init).get(i):" "+dic2ans.get(init).get(i)));
				}
			}
		}
	}
	
	// 21:50-22:16 22:32WA
	// ICPC Asia Japan 2001 B
	class AOJ1225{
		final int INF=Integer.MAX_VALUE/4;
		AOJ1225(){
			while(true){
				ArrayList<Deal> sell=new ArrayList<Deal>(),buy=new ArrayList<Deal>();
				HashMap<String,Dealer> dealer=new HashMap<String,Dealer>();
				HashMap<String,Commodities> comm=new HashMap<String, Commodities>();
				int N=sc.nextInt();
				if(N==0)	break;
				for(int I=0; I<N; I++){
					String d=sc.next(),ff=sc.next(),c=sc.next();
					int a=sc.nextInt();
					boolean f=ff.equals("BUY");
					if(!dealer.containsKey(d))	dealer.put(d, new Dealer(0, 0));
					ArrayList<Deal> tmp=(f?sell:buy);
					int idx=-1,m=(f?INF:-1);
					for(int i=0; i<tmp.size(); i++){
						if(tmp.get(i).c.equals(c) && !tmp.get(i).d.equals(d) && (f?m>tmp.get(i).a:m<tmp.get(i).a) && (f?a>=tmp.get(i).a:a<=tmp.get(i).a)){
							m=tmp.get(i).a;	idx=i;
						}
					}
					if(idx>=0){
						a=(a+tmp.get(idx).a)/2;
						if(!comm.containsKey(c))	comm.put(c, new Commodities(a));
						else	comm.get(c).add(a);
						dealer.get(d).add(f?0:a, f?a:0);
						dealer.get(tmp.get(idx).d).add(f?a:0, f?0:a);
						tmp.remove(idx);
					}else{
						tmp=(f?buy:sell);
						tmp.add(new Deal(d,c,a));
					}
				}
				ArrayList<String> keys=new ArrayList<String>();
				for(String key:comm.keySet())	keys.add(key);
				Collections.sort(keys);
				for(String key:keys){
					Commodities now=comm.get(key);
					System.out.println(key+" "+now.min+" "+now.getAve()+" "+now.max);
				}
				System.out.println("--");
				keys.clear();
				for(String key:dealer.keySet())	keys.add(key);
				Collections.sort(keys);
				for(String key:keys)	System.out.println(key+" "+dealer.get(key).out+" "+dealer.get(key).in);
				System.out.println("----------");
			}
		}
		class Deal{
			String d,c;	int a;
			Deal(String d,String c,int a){	this.d=d; this.c=c; this.a=a;}
		}
		class Dealer{
			int in,out;
			Dealer(int in,int out){this.in=in; this.out=out;}
			void add(int in,int out){this.in+=in; this.out+=out;}
		}
		class Commodities{
			int max,min,sum,num;
			Commodities(int a){
				this.max=a; this.min=a; this.sum=a;
				this.num=1;
			}
			void add(int a){
				this.max=max(this.max,a);	this.min=min(this.min,a);
				this.sum+=a;	this.num++;
			}
			int getAve(){ return this.sum/this.num;}
		}
	}

}