lightoj1366Pair of Touching Circles

思路:给出一个矩形的宽w和高h,要在这个矩形中画两个圆,圆是外切的,且圆完全在矩形内部,圆心在整数点上面,两个的半径都是整数。求有多少种画法。

因为是相切的,所以两点之间的距离是其半径和,为整数。我们可以枚举两个圆A,B的相对位置,A在B的左下方,枚举的是B相对A的x,y值,x,y不同时为0。这样以来x <= h/2,y <= w/2。

这样之后就要求能装下这两个圆的最小矩形了(平行于坐标轴的)。看是否满足条件完全在大矩形内,最后求这个大矩形中有多少个小矩形。

有两种情况:

1:AB的圆心连线与坐标轴平行。

2:AB的圆心连线不与坐标轴平行。

主要是第二种情况,因为只枚举了B在A的右上方的情况,还有右下方没有枚举,但是又对称性可知,右上等于右下,乘2就是了。

// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <climits>
using namespace std;
#define DEBUG
#ifdef DEBUG
#define debug(...) printf( __VA_ARGS__ )
#else
#define debug(...)
#endif
#define CLR(x) memset(x, 0,sizeof x)
#define MEM(x,y) memset(x, y,sizeof x)
#define pk push_back
template<class T> inline T Get_Max(const T&a,const T&b){return a < b?b:a;}
template<class T> inline T Get_Min(const T&a,const T&b){return a < b?a:b;}
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
const double eps = 1e-10;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1010;
int GetDistance(int x,int y){
	int m = (int)sqrt(x*x+y*y+0.1);
	if (m*m==x*x+y*y) return m;
	return 0;
}
int v[maxn][maxn];
inline void Init(){
	for (int i = 0;i <= 500;++i)
		for (int j = 0;j <= 500;++j)
			v[i][j] = GetDistance(i,j);
}
int h,w;
inline int In(int x,int y){
	return (h-x+1)*(w-y+1);
}
inline void Solve(){
	LL sum = 0;
	for (int i = 0;i <= h/2;++i){
		for (int j = 0;j <= w/2;++j){
			if (v[i][j]){
				for (int k = 1;k < v[i][j];++k){
					int y1 = Get_Min(-k,j-v[i][j]+k), y2 = Get_Max(k,j+v[i][j]-k);
					int x1 = Get_Min(-k,i-v[i][j]+k), x2 = Get_Max(k,i+v[i][j]-k);
					int x = x2 - x1;
					int y = y2 - y1;
					if (x>h || y>w) continue;
					int tmp = In(x,y);
					if (i>0&&j>0) tmp <<= 1;
					sum += 1LL*tmp;
					// debug("here\n");
				}
			}
		}
	}
	cout << sum << endl;
}
int main()
{	
	// freopen("in.txt","r",stdin);
	// freopen("out.txt","w",stdout);
	int t, icase = 0;
	scanf("%d",&t);
	Init();
	while(t--){
		scanf("%d%d",&h,&w);
		printf("Case %d: ", ++icase);
		Solve();
	}
	return 0;
}


你可能感兴趣的:(lightoj,基础几何)