HDU 3663 Power Stations 精确覆盖
题意:每个城市i有xi->yi天可以成为发射站,发射站覆盖范围为与该站有一条边链接的城市。
同时,每个每天城市必须且只能被一个发射站覆盖
天数D<=5。 每个城市的发射站关闭后就不再开启。即只能选择一段区间。
问若能做到,则输出每个城市开启时间与关闭时间
否则输出No solution
做法:
1.天数城市可独立看待,故每个城市每天看做一列。
2.在此区间内取一段子区间,注意到D很小,可枚举起点时刻终点时刻,每个城市每个方案作为一行。
3.对每个方案可覆盖到的城市及各天,则对该行该列设1
4.为解决每个城市只能取一段区间,则对每个城市设置一个新的列,该城市所有方案在该列设1,使不重复选择。
5.注意设置每个城市发射站未开启的方案行。因为不开是可行的。6。
注意多输出一行空行
//2014.11.7
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; #define N 1004 #define M 850 #define T 820000 #define INF 0x3f3f3f3f vector<int>vec[66]; int dir[10]; bool g[66][66]; vector<int>v; struct Day{ int x,y; Day(){}; Day(int xx, int yy): x(xx), y(yy){}; }p[66], ans[66], rec[N]; int yingying, f[N]; void dabiao(){ int i; dir[0] = 0; for(i = 1; i <= 5; i++) dir[i] = i + dir[i-1]; } struct DLX{ int L[T], R[T], U[T], D[T]; int head[N]; int cnt[M], col[T], row[T], id, n, m; void init(int nn, int mm){ this->n = nn; this->m = mm; int i; for(i = 0; i <= m; i++){ D[i] = U[i] = i; L[i] = i-1; R[i] = i + 1; } id = m + 1; R[m] = 0; L[0] = m; memset(cnt, 0, sizeof(cnt)); memset(head, -1, sizeof(head)); } void add(int r, int c){ D[id] = c; U[id] = U[c]; D[U[c]] = id; U[c] = id; if(head[r] < 0 ){ head[r] = L[id] = R[id] = id; } else { L[id] = head[r]; R[id] = R[head[r]]; L[R[head[r]]] =id; R[head[r]] = id; head[r] = id; } cnt[c] ++; col[id] = c; row[id] =r; id ++; } void del(int x){ int i, j; L[R[x]] = L[x]; R[L[x]] = R[x]; for(i = D[x]; i != x; i = D[i]){ for(j = R[i]; j != i; j = R[j]){ cnt[col[j]] --; U[D[j]] = U[j]; D[U[j]] = D[j]; } } } void resume(int x){ int i, j; for(i = U[x]; i != x; i = U[i]){ for(j = L[i]; j != i; j = L[j]){ cnt[col[j]] ++; D[U[j]] = j; U[D[j]] = j; } } L[R[x]] = x; R[L[x]] = x; } bool dfs(){ if(R[0] == 0) return true; int idx , temp, i, j; temp = INF; for(i = R[0]; i != 0; i = R[i]){ if(cnt[i] < temp){ temp = cnt[i]; idx = i; } } if(temp == 0) return false; del(idx); for(i = D[idx]; i != idx; i = D[i]){ Day tttt = ans[f[row[i]]]; ans[f[row[i]]] = rec[row[i]]; for(j = R[i]; j != i; j = R[j]){ del(col[j]); } if(dfs()) return true; for(j = L[i]; j != i; j = L[j]){ resume(col[j]); } ans[f[row[i]]] = tttt; } resume(idx); return false; } }dlx; bool gao(int n, int d){ int sum = 0, i, j, k, t, tt; for(i = 1; i <= n; i++){ sum += dir[p[i].y - p[i].x]; } dlx.init(sum, n * d + n); sum = 0; for(i = 1; i <= n; i++){ for(j = p[i].x; j <= p[i].y; j++){ for(k = j; k <= p[i].y; k++){ ++sum; for(tt = 0; tt < vec[i].size(); tt++){ for(t = j; t <= k; t++){ dlx.add(sum, (vec[i][tt]-1)*d+t); } } dlx.add(sum, n * d +i); rec[sum] = Day(j, k); f[sum] = i; } } } for(i = 1; i <= n; i ++){ dlx.add(++sum, n * d + i); f[sum] = n + 1; } return dlx.dfs(); } int main(void){ int n, m, d, i, j, x, y; dabiao(); while(scanf("%d%d%d", &n, &m, &d) != EOF){ fill(vec, vec+66, vector<int>() ); memset(g, false, sizeof(g)); while(m--){ scanf("%d%d", &x, &y); if(g[x][y]) continue; g[x][y] = g[y][x] = true; vec[x].push_back(y); vec[y].push_back(x); } for(i = 1; i <= n; i++){ scanf("%d%d", &p[i].x, &p[i].y); vec[i].push_back(i); ans[i] = Day(0, 0); } yingying = n; if(gao(n, d)){ for(i = 1; i <= n; i++){ printf("%d %d ", ans[i].x, ans[i].y); } } else printf("No solution "); printf(" "); } return 0; }
HDU 2828 Lamp
重复覆盖+判断冲突
题意:有N盏灯可以由M个开关控制,对于第i盏灯,当条件A|| B || C。。。满足则灯亮,条件X为j开关OFF或ON状态。
问开关处于何种状态时,灯是全开的。SPJ
做法:
建图的第一部分很简单,以N盏灯为列,每个开关的开/关状态各为一行,对处于此状态为亮的灯为1.
然后是开关的状态只能取一个的解决方法。对于每个开关状态on / off是否采用,设置vis数组,若dfs时对应的另一个状态已经采用,则此状态非法,不搜。
以上,可解决。
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; #define N 1004 #define T 1000004 #define INF 0x3f3f3f3f int f[N][N>>1], ans[504]; vector<int>v; int M ; struct DLX{ int r[T], l[T], u[T], d[T]; int cnt[N], col[T], row[N], head[N]; bool vis[N]; int n, id; void init(int n){ this->n = n; int i; for(i = 0; i <= n; i++){ d[i] = u[i] = i; l[i] = i - 1; r[i] = i + 1; } id = n + 1; r[n] = 0; l[0] = n; memset(cnt, 0, sizeof(cnt)); memset(vis, false, sizeof(vis)); memset(head, -1, sizeof(head)); } void add(int R, int C){ d[id] = C; u[id] = u[C]; d[u[C]] = id; u[C] = id; if(head[R] < 0 ){ head[R] = l[id] = r[id] = id; } else { l[id] = head[R]; r[id] = r[head[R]]; l[r[head[R]]] =id; r[head[R]] = id; head[R] = id; } cnt[C] ++; col[id] = C; row[id] =R; id ++; } void remove(int x){ int i; for(i = u[x]; i != x; i = u[i]){ l[r[i]] = l[i]; r[l[i]] = r[i]; } } void resume(int x){ int i; for(i = d[x]; i != x; i = d[i]){ l[r[i]] = i; r[l[i]] = i; } } bool dfs(){ if(r[0] == 0) return true; int i, c = r[0], j; for(i = r[0]; i != 0; i = r[i]){ if(cnt[i] <cnt[c]) c = i; } for(i = d[c]; i != c; i = d[i]){ if(vis[row[i]^1] ) continue; vis[row[i]] = true; remove(i); for(j = r[i]; j != i; j = r[j]){ remove(j); } if(dfs()) return true; for(j = l[i]; j != i; j = l[j]) resume(j); resume(j); resume(i); vis[row[i]] = false; } return false; } }dlx; bool gao(int n, int m){ dlx.init(n); m <<= 1; int i, j; for(i = 0; i < m; i++){ for(j = 1; j <= n; j++){ if(f[i][j]){ dlx.add(i, j); } } } return dlx.dfs(); } int main(){ int n, m, i, k, x; char op[10]; while(scanf("%d%d", &n, &m) != EOF){ memset(f, 0, sizeof(f)); M = n; for(i = 1; i <= n; i++){ scanf("%d", &k); while(k--){ scanf("%d%s", &x, op); x--; if(op[1] == 'N'){ f[x<<1][i] = 1; } else f[x<<1|1][i] = 1; } } if(gao(n, m)){ for(i = 0; i < m; i++){ printf("%s%c", dlx.vis[i<<1] ? "ON": "OFF", i == m - 1? ' ' : ' '); } } else printf("-1 "); } return 0; }
zoj 3209 Treasure Map
题意:在 n*m的平面中有p (1 <= n, m <= 30, 1 <= p <= 500)个小矩形,每个小矩形有其所在位置,问从中选出最少数目个使得覆盖整个平面并且不重合。
直接暴力碾压过去。。对每个小矩形为行,为其能覆盖的点(格子?)为列,跑DLX
注意每个点应该[x0,x1), [y0, y1) 即统一只覆盖某边界
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define N 505 #define M 1005 #define T 500005 #define INF 0x3f3f3f3f struct DLX{ int r[T], u[T], l[T], d[T]; int cnt[M], col[T], head[N]; int n, id; void init(int nt){ this->n = nt; int i; for(i = 0; i <= n; i++){ d[i] = u[i] = i; l[i] = i - 1; r[i] = i + 1; } id = n + 1; r[n] = 0; l[0] = n; memset(cnt, 0, sizeof(cnt)); memset(head, -1, sizeof(head)); } void add(int rr, int cc){ d[id] = cc; u[id] = u[cc]; d[u[cc]] = id; u[cc] = id; if(head[rr] < 0){ head[rr] = l[id] = r[id] = id; } else { l[id] = head[rr]; r[id] = r[head[rr]]; l[r[head[rr]]] = id; r[head[rr]] = id; head[rr] = id; } cnt[cc] ++; col[id] = cc; id ++; } void remove(int x){ int i, j; l[r[x]] = l[x]; r[l[x]] = r[x]; for(i = d[x]; i != x; i = d[i]){ for(j = r[i]; j != i; j = r[j]){ cnt[col[j]] --; u[d[j]] = u[j]; d[u[j]] = d[j]; } } return ; } void resume(int x){ int i, j; for(i = u[x]; i != x; i = u[i]){ for(j = l[i]; j != i; j = l[j]){ cnt[col[j]] ++; d[u[j]] = j; u[d[j]] = j; } } l[r[x]] = x; r[l[x]] = x; } int dfs(){ if(r[0] == 0) { return 0;} int idx, temp = INF, ans = INF, i, j; for(i = r[0]; i != 0; i = r[i]){ if(cnt[i] < temp){ temp = cnt[i]; idx = i; } } // printf("%d ", idx); if(temp == 0) return INF; remove(idx); for(i = d[idx]; i != idx; i = d[i]){ for(j = r[i]; j != i; j = r[j]){ remove(col[j]); } ans = min(ans, dfs()); for(j = l[i]; j != i; j = l[j]){ resume(col[j]); } } resume(idx); return ans + 1; } }dlx; int main(void){ int TC, n, p, m, i, j, k, ans; int x1, y1, x2, y2; scanf("%d", &TC); while(TC--){ scanf("%d%d%d", &n, &m, &p); dlx.init(m*n); for(i = 1; i <= p; i++){ scanf("%d%d%d%d", &x1, &y1, &x2, &y2); for(j = x1; j < x2; j++){ for(k = y1; k < y2; k++){ dlx.add(i, 1 + j * m + k); } } } ans = dlx.dfs(); if(ans >= INF) ans = -1; printf("%d ", ans); } return 0; }
HDU 3498 whosyourdaddy
题意:攻击一个点可以同时攻击其相邻点,(不超过4个) ,问最少攻击多少个点能攻击完所有点。
做法。。裸。。。注意剪枝
if(ct + H() > ANS) return; 是过不了的。。
要if(ct + H() >= ANS) return;才行
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define N 60 #define T 4000 #define INF 0x3f3f3f3f bool f[N][N]; int ANS; struct DLX{ int l[T], r[T], u[T], d[T]; int cnt[N], head[N], row[T], col[T]; bool vis[N]; int id, n; void init(int nt){ this->n = nt; int i; for(i = 0; i <= n; i++){ d[i] = u[i] = i; l[i] = i - 1; r[i] = i + 1; } id = n + 1; r[n] = 0; l[0] = n; memset(cnt, 0, sizeof(cnt)); memset(head, -1, sizeof(head)); } void add(int R, int C){ d[id] = C; u[id] = u[C]; d[u[C]] = id; u[C] = id; if(head[R] < 0 ){ head[R] = l[id] = r[id] = id; } else { l[id] = head[R]; r[id] = r[head[R]]; l[r[head[R]]] =id; r[head[R]] = id; head[R] = id; } cnt[C] ++; col[id] = C; row[id] =R; id ++; } void remove(int x){ int i, j; for(i = u[x]; i != x; i = u[i]){ l[r[i]] = l[i]; r[l[i]] = r[i]; } } int H(){ memset(vis, false, sizeof(vis)); int ans = 0, i, j, k; for(i = r[0]; i != 0; i = r[i]){ if(vis[i]) continue; ans ++; vis[i] = true; for(j = d[i]; j != i; j = d[j]){ for(k = r[j]; k != j; k = r[k]){ vis[col[k]] = true; } } } return ans; } void resume(int x){ int i; for(i = d[x]; i != x; i = d[i]){ l[r[i]] = i; r[l[i]] = i; } } void dfs(int ct){ if(ct + H() >= ANS) return; if(r[0] == 0) { ANS = min(ANS, ct); return; // return true; } int idx, temp = INF, ans = INF, i, j; for(i = r[0] ;i != 0; i = r[i]){ if(cnt[i] < temp){ temp = cnt[i]; idx = i; } } // printf("%d ", idx); for(i = d[idx]; i != idx; i =d[i]){ remove(i); for(j = r[i]; j != i; j = r[j]){ remove(j); } //if(dfs(ct+1)) ans = true; dfs(ct + 1); for(j = l[i]; j != i; j = l[j]){ resume(j); } resume(i); } // return false; } }dlx; int main(){ int n, m, x, y; int i, j; while(scanf("%d%d", &n, &m) != EOF){ dlx.init(n); memset(f, false, sizeof(f)); while(m--){ scanf("%d%d", &x, &y); f[x][y] = f[y][x] = true; } for(i = 1; i <= n; i++){ f[i][i] = true; for(j = 1; j <= n; j++){ if(f[i][j]) dlx.add(i, j); } } ANS = n; dlx.dfs(0); printf("%d ", ANS); } return 0; }
HDU 3529 Bomberman - Just Search!
题意:炸弹人游戏,在空地放炸弹可以炸到以它为十字中心的最近的砖块,如果路上有石头冲击波就被拦住了。现在设所有炸弹同时爆炸,问最少放多少个炸弹。
做法:继续裸题。。就是为了练敲板正确度
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define N 240 #define M 44 #define T 11560 #define INF 0x3f3f3f3f int ans, mapa[22][22], mapb[22][22]; char map[22][22]; bool f[N][M]; /* struct DLX{ int l[T], r[T], u[T], d[T]; int head[N], row[T], col[T], cnt[M]; bool vis[M]; int id, n; }dlx; */ struct DLX{ int l[T], r[T], u[T], d[T]; int cnt[N], head[N], row[T], col[T]; bool vis[N]; int id, n; void init(int nt){ this->n = nt; int i; for(i = 0; i <= n; i++){ d[i] = u[i] = i; l[i] = i - 1; r[i] = i + 1; } id = n + 1; r[n] = 0; l[0] = n; memset(cnt, 0, sizeof(cnt)); memset(head, -1, sizeof(head)); } void add(int rr, int cc){ d[id] = cc; u[id] = u[cc]; d[u[cc]] = id; u[cc] = id; if(head[rr] < 0){ head[rr] = l[id] = r[id ] = id; } else{ l[id] = head[rr]; r[id] = r[head[rr]]; l[r[head[rr]]] = id; r[head[rr]] = id; head[rr] = id; } col[id] = cc; row[id] = rr; cnt[cc] ++; id ++; } void del(int x){ int i; for(i = u[x]; i != x; i = u[i]) { l[r[i]] = l[i]; r[l[i]] = r[i]; } } int H(){ memset(vis, false, sizeof(vis)); int i, j, k, ans = 0; for(i = r[0]; i != 0; i =r[i]){ if(vis[i]) continue; ans ++; vis[i] = true; for(j = d[i]; j != i; j = d[j]){ for(k = r[j] ;k != j; k = r[k]){ vis[col[k]] = true; } } } return ans; } void resume(int x){ int i; for(i =d[x]; i != x; i =d[i]){ l[r[i]] = i; r[l[i]] = i; } } void dfs(int ct){ if(ct + H() >= ans) return; if(r[0] == 0){ ans = min(ans, ct); return; } int i, idx, temp = INF, j; for(i = r[0]; i != 0; i = r[i]){ if(cnt[i] < temp){ temp = cnt[i]; idx = i; } } for(i = d[idx]; i != idx; i =d[i]){ del(i); for(j = r[i]; j != i; j =r[j]){ del(j); } dfs(ct + 1); for(j = l[i]; j != i; j = l[j]){ resume(j); } resume(i); } } }dlx; int gox[4] = {0, 0, -1, 1}, goy[4] = {-1, 1, 0, 0}; int main(){ int n, m, i, j, ida, idb; int k, xx, yy; while(scanf("%d%d", &n, &m) != EOF){ ida = idb = 0; for(i = 1; i <= n; i++){ scanf("%s", map[i]+1); for(j = 1; j <= m; j++){ if(map[i][j] == '.') mapa[i][j] = ++ida; else if(map[i][j] == '#') mapb[i][j] = ++idb; } } dlx.init(idb); memset(f, 0, sizeof(f)); for(i = 2; i < n; i++){ for(j = 2; j < m; j++){ if(map[i][j] == '.'){ //void build(int x, int y){ for(k = 0; k < 4; k++){ xx = i + gox[k]; yy = j + goy[k]; while(true){ if(map[xx][yy] == '*') break; if(map[xx][yy] == '#'){ f[mapa[i][j]][mapb[xx][yy]] = true; break; } xx += gox[k]; yy += goy[k]; } } } } } for(i = 1; i <= ida; i++){ for(j = 1; j <= idb; j++){ if(f[i][j]) dlx.add(i, j); } } //printf("!! "); ans = ida; dlx.dfs(0); printf("%d ", ans); } return 0; }
HDU 2295 Radar
题意:对于一个发射站可以覆盖以他为圆心的半径是 r的园内的城市,每个发射站半径相同,问使得从备选的M个发射站中选出K个覆盖所有N个城市的最小半径是多少。
二分半径,重复覆盖,搜索时当ct+H() > K 就是不行
1. 1 ≤ T ≤ 20
2. 1 ≤ N, M ≤ 50
3. 1 ≤ K ≤ M
4. 0 ≤ X, Y ≤ 1000
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define N 55 #define T 3003 #define INF 0x3f3f3f3f int dis[N][N]; int K; struct DLX{ int l[T], r[T], u[T], d[T]; int cnt[N], col[T], row[T], head[N]; bool vis[N]; int n, id; void init(int nt){ int i; this->n = nt; for(i = 0; i <= n; i++){ u[i] = d[i] = i; l[i] = i -1; r[i] = i + 1; } l[0] = n; r[n] = 0; id = n + 1; memset(cnt, 0, sizeof(cnt)); memset(head, -1, sizeof(head)); } void add(int x, int y){ u[id] = u[y]; d[id] = y; d[u[y]] = id; u[y] = id; if(head[x] == -1){ head[x] = l[id] = r[id] = id; }else{ l[id] = head[x]; r[id] = r[head[x]]; l[r[head[x]]] = id; r[head[x]] = id; } col[id] = y; row[id] = x; cnt[y] ++; id++; } void del(int x){ int i; for(i = u[x]; i != x; i = u[i]){ l[r[i]] = l[i]; r[l[i]] = r[i]; } } void resume(int x){ int i; for(i = d[x]; i != x; i = d[i]){ l[r[i]] = r[l[i]] = i; } } int H(){ memset(vis, false, sizeof(vis)); int i, j,k, ans = 0; for(i = r[0]; i != 0; i = r[i]){ if(vis[i]) continue; ans ++; vis[i] = true; for(j = d[i]; j != i; j = d[j]){ for(k = r[j]; k != j; k = r[k]){ vis[col[k]] = true; } } } return ans; } bool dfs(int ct){ if(ct + H() > K) return false; if(r[0] == 0) return true; int i, j, idx, temp = INF; for(i = r[0]; i != 0; i = r[i]){ if(cnt[i] < temp){ temp = cnt[i]; idx = i; } } for(i = d[idx]; i != idx; i = d[i]){ del(i); for(j = r[i]; j != i; j =r[j]){ del(j); } if(dfs(ct + 1)) return true; for(j = l[i]; j != i; j = l[j]){ resume(j); } resume(i); } return false; } }dlx; int n, m; struct point{ int x, y; }p[N], q[N]; void cal(void ){ int i, j; for(i = 1; i <= m; i++) for(j = 1; j <= n; j++) dis[i][j] = (q[i].x-p[j].x)* (q[i].x-p[j].x) + (q[i].y-p[j].y)* (q[i].y-p[j].y); } void build(int mid){ dlx.init(n); int i, j; for(i = 1; i <= m; i++){ for(j = 1; j <= n; j++){ if(mid >= dis[i][j]){ dlx.add(i, j); } } } } int main(){ int TC; scanf("%d", &TC); int i, j; while(TC--){ scanf("%d%d%d", &n, &m, &K); for(i = 1; i <= n; i++){ scanf("%d%d", &p[i].x, &p[i].y); } for(j = 1; j <= m; j++){ scanf("%d%d", &q[j].x, &q[j].y); } cal(); int low = 0, high =INF, mid, ans; while(low <= high){ mid = (low + high) >> 1; build(mid); if(dlx.dfs(0)){ ans = mid; high = mid - 1; } else low = mid + 1; } printf("%.6f ", (double)sqrt((double)ans)); } return 0; }
HDU 3656 Fire station
题意类似,从N个城市中选M个建消防站,使得所有城市到离他最近的消防站的距离最小。
不过直接对一大波范围二分会T,注意到半径一定是离消防站某个城市的距离,处理出城市两两之间所有距离,二分+重复覆盖
s (1 ≤ M ≤N ≤ 50), (0 ≤ Xi, Yi ≤ 10000)
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 55 #define T 4003 #define INF 0x3f3f3f3f int n, m; int dis[N][N], num[T]; int maxn; struct DLX{ int l[T], r[T], u[T], d[T]; int cnt[N], col[T], head[N]; bool vis[N]; int id, n; void init(int nt){ this->n = nt; int i; for(i = 0; i <= n; i++){ u[i] = d[i] = i; l[i] = i-1; r[i] = i + 1; } l[0] = n; r[n] = 0; memset(cnt, 0, sizeof(cnt)); memset(head, -1, sizeof(head)); id = n + 1; } void add(int x, int y){ d[id] = y; u[id] = u[y]; d[u[y]] = id; u[y] = id; if(head[x] == -1){ head[x] = l[id] = r[id] = id; } else{ l[id ] = head[x]; r[id] = r[head[x]]; l[r[head[x]]] = id; r[head[x]] = id; head[x] = id; } col[id] = y; cnt[y] ++; id ++; } void del(int x){ int i; for(i = u[x]; i != x; i = u[i]){ l[r[i]] = l[i]; r[l[i]] = r[i]; } } void resume(int x){ int i; for(i = d[x]; i != x; i = d[i]){ l[r[i]] = r[l[i]] = i; } } int H(){ int i, j, k, ans = 0; memset(vis, false, sizeof(vis)); for(i = r[0]; i != 0; i = r[i]){ if(vis[i]) continue; ans ++; vis[i] = true; for(j = d[i]; j != i; j = d[j]){ for(k = r[j] ; k != j; k = r[k]){ vis[col[k]] = true; } } } return ans; } bool dfs(int ct){ if(ct + H() > m) return false; if(r[0 ] == 0) return true; int i, j, idx, temp = INF; for(i = r[0]; i != 0; i = r[i]){ if(cnt[i] < temp){ temp = cnt[i]; idx = i; } } for(i = d[idx]; i != idx; i = d[i]){ del(i); for(j = r[i]; j != i; j =r[j]){ del(j); }if(dfs(ct + 1)) return true; for(j = l[i]; j != i; j = l[j]){ resume(j); } resume(i); } return false; } }dlx; struct point{ int x, y; }p[N]; void cal(){ int i, j; dis[0][0] = 0; for(i = 1; i <= n; i++){ for(j = 1; j <= n; j++){ dis[i][j] = (p[i].x-p[j].x)*(p[i].x-p[j].x) +(p[i].y-p[j].y)*(p[i].y-p[j].y); // dis[0][0] = max(dis[0][0], dis[i][j]); // printf("%d ", dis[i][j]); num[++maxn] = dis[i][j]; } //printf(" "); } } void build(int mid){ int i, j; dlx.init(n); for(i = 1; i <= n; i++){ for(j = 1; j <= n; j++){ if(dis[i][j] <= mid) dlx.add(i, j); } } } int main(void){ int TC, i; int low, mid, ans, high; scanf("%d", &TC); while(TC--){ scanf("%d%d", &n, &m); for(i = 1; i <= n; i++){ scanf("%d%d", &p[i].x, &p[i].y); } maxn = 0; cal(); sort(num + 1, num + 1 + maxn); // for(i = 1; i <= maxn; i++) printf("%d ", num[i]); maxn = unique(num+1, num+1+maxn)-num; // printf("%d ", maxn); low = 1; high = maxn-1; while(low <= high){ mid = (low+high)>>1; build(num[mid]); if(dlx.dfs(0)){ ans = num[mid]; high = mid -1; } else low = mid + 1; } printf("%.6f ", sqrt((double)ans)); } return 0; }
HDU 2518
题意:http://acm.hdu.edu.cn/showproblem.php?pid=2518
/* #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 88 #define M 140 #define INF 0x3f3f3f3f #define T 420000 int kind[12] = {4, 2, 1, 4, 8, 4, 8, 4, 8, 4, 8, 8}; int row; int gox[12][8][4] = { { /****** 0 0 000 000 0 0 0 0 000 000 0 0 ******** {1,2,2,2}, {1,2,2,2}, {0,0,1,2}, {0,0,1,2} }, { /****** 00000 0 0 0 0 0 ******** {0,0,0,0},{1,2,3,4} }, { /****** 0 000 0 ******** {1, 1, 1, 2} }, { /****** 0 0 000 00 00 000 0 0 0 0 00 00 ******** {0,1,1,1},{0,0,1,1},{0,1,2,2},{0,1,2,2} }, { /****** 0 00 0000 0 0000 0 0 0 0 0 0 00 ******** {1,1,1,1}, {0,1,2,3},{0,0,0,1},{1,2,3,3}, /****** 00 0 0000 0 0 0 0 0 0000 0 0 00 ******** {0,0,0,1},{0,1,2,3},{1,1,1,1},{1,2,3,3} }, { /****** 0 00 00 0 00 00 00 00 00 0 0 00 ******* {1,1,2,2},{0,1,1,2},{0,1,1,2},{1,1,2,2} }, {/****** 0 0 0000 0 0 0 0000 0 0000 00 0 0 0000 0 0 00 0 00 00 0 0 0 0 0 ******** {1,1,1,1},{1,1,2,3}, {0,0,0,1}, {1,2,2,3}, {1,1,1,1},{1,2,2,3},{0,0,0,1},{1,1,2,3} }, { /****** 0 00 0 00 000 0 000 0 0 00 0 00 ******** {1,1,1,2},{0,1,2,2}, {1,1,1,2},{0,1,2,2} }, {/****** 0 0 00 0 0 0 00 0 00 000 00 000 00 000 00 000 00 0 0 0 00 0 0 0 ******** / {1,1,2,2},{1,1,1,2},{0,1,1,2},{1,1,1,2},{1,1,2,2},{1,1,1,2},{0,1,1,2},{1,1,1,2} }, {/****** 0 000 0 0 0 0 000 000 000 0 0 0 ******** / {1,2,2,2}, {0,0,1,2}, {1,1,1,2}, {1,1,1,2} }, {/****** 00 0 000 00 00 0 000 00 000 00 00 00 000 00 00 00 00 0 00 0 ***** / {0,1,1,1},{1,1,2,2},{0,0,1,1},{0,1,1,2},{0,1,1,1}, {1,1,2,2},{0,0,1,1},{0,1,1,2} }, {/****** 000 0 00 0 000 0 00 0 00 00 000 0 00 00 000 0 0 00 0 00 0 0 0 0 ******* / {0,0,1,1},{1,1,2,3}, {0,1,1,1},{1,2,2,3},{0,0,1,1},{1,1,2,3}, {0,1,1,1},{1,2,2,3} } }; int goy[12][8][4] = { { /****** 0 0 000 000 0 0 0 0 000 000 0 0 ******** / {0,0,1,2}, {0,-2,-1,0}, {1,2,2,2}, {1,2,0,0} }, { /****** 00000 0 0 0 0 0 ******** / {1,2,3,4},{0,0,0,0} }, { /****** 0 000 0 ******** / {-1,0,1,0} }, { /****** 0 0 000 00 00 000 0 0 0 0 00 00 ******** / {2,0,1,2},{1,2,0,2},{1,0,0,1},{1,1,0,1} }, { /****** 0 00 0000 0 0000 0 0 0 0 0 0 00 ******** / {0,1,2,3},{1,0,0,0},{1,2,3,3}, {0,0,-1,0}, /****** 00 0 0000 0 0 0 0 0 0000 0 0 00 ******** / {1,2,3,0},{1,1,1,1},{-3,-2,-1,0},{0,0,0,1} }, { /****** 0 00 00 0 00 00 00 00 00 0 0 00 ******** / {0,1,1,2},{1,-1,0,-1},{1,1,2,2},{-1,0,-2,-1} }, {/****** 0 0 0000 0 0 0 0000 0 0000 00 0 0 0000 0 0 00 0 00 00 0 0 0 0 0 ******** / {-1,0,1,2},{0,1,0,0},{1,2,3,2},{0,-1,0,0},{-2,-1,0,1},{0,0,1,0},{1,2,3,1},{-1,0,0,0} }, { /****** 0 00 0 00 000 0 000 0 0 00 0 00 ******** / {-2,-1,0,-2},{1,1,1,2},{0,1,2,2},{1,0,-1,0} }, {/****** 0 0 00 0 0 0 00 0 00 000 00 000 00 000 00 000 00 0 0 0 00 0 0 0 ******** / {0,1,-1,0},{0,1,2,1},{1,-1,0,0},{-1,0,1,1},{-1,0,0,1},{-2,-1,0,-1},{1,1,2,1},{-1,0,1,-1} }, {/****** 0 000 0 0 0 0 000 000 000 0 0 0 ******** / {0,-1,0,1},{1,2,1,1},{-2,-1,0,0},{0,1,2,0} }, {/****** 00 0 000 00 00 0 000 00 000 00 00 00 000 00 00 00 00 0 00 0 ***** / {1,-1,0,1},{0,1,0,1},{1,2,0,1},{1,0,1,1},{1,0,1,2},{-1,0,-1,0},{1,2,1,2},{1,0,1,0} }, {/****** 000 0 00 0 000 0 00 0 00 00 000 0 00 00 000 0 0 00 0 00 0 0 0 0 ******** / {1,2,-1,0},{0,1,1,1},{1,-2,-1,0},{0,0,1,1},{1,2,2,3},{-1,0,-1,-1},{1,1,2,3},{0,-1,0,-1} } }; int ans ; struct DLX{ int l[T], r[T], u[T], d[T]; int col[T], cnt[N], head[T]; int id, n; void init(int nt){ this->n = nt; int i; for(i = 0; i <= n; i++){ d[i] = u[i] = i; l[i] = i - 1; r[i] = i + 1; } l[0] = n; r[n] = 0; memset(cnt, 0, sizeof(cnt)); memset(head, -1, sizeof(head)); id= n +1; } void add(int x, int y){ u[id] = u[y]; d[id] = y; d[u[y]] = id; u[y] = id; if(head[x] == -1){ head[x] = l[id] = r[id] = id; } else{ r[id] = r[head[x]]; l[id] = head[x]; l[r[id]] = id; r[l[id]] = id; head[x] = id; } cnt[y] ++; col[id] = y; id++; } void del(int x){ int i, j; l[r[x]] = l[x]; r[l[x]] = r[x]; for(i = d[x]; i != x; i = d[i]){ for(j = r[i]; j != i; j = r[j]){ cnt[col[j]] --; u[d[j]] = u[j]; d[u[j]] = d[j]; } } } void resume(int x){ int i, j; for(i = u[x]; i != x; i = u[i]){ for(j = l[i]; j != i; j = l[j]){ cnt[col[j]] ++; d[u[j]] = j; u[d[j]] = j; } } l[r[x]] = x; r[l[x]] = x; } void dfs(){ if(r[0] == 0) { ans++; return; } int idx, temp, i, j; temp = INF; for(i = r[0]; i != 0; i = r[i]){ if(cnt[i] < temp){ temp = cnt[i]; idx = i; } } if(temp == 0) return; del(idx); for(i = d[idx]; i != idx; i = d[i]){ for(j = r[i]; j != i; j = r[j]){ del(col[j]); } dfs(); for(j = l[i]; j != i; j = l[j]){ resume(col[j]); } } resume(idx); } }dlx; int n, m; void color(int domi, int ang, int x, int y){ int i, j, xx, yy; for(i = 0; i < 4; i++){ xx = x + gox[domi][ang][i]; yy = y + goy[domi][ang][i]; if(xx < 1 || xx > n || yy < 1 || yy > m) return; } dlx.add(++row, domi+1); dlx.add(row, m*(x-1)+y+12); for(i = 0; i < 4; i++){ xx = x + gox[domi][ang][i]; yy = y + goy[domi][ang][i]; dlx.add(row, m*(xx-1)+yy+12); } } int dabiao[10]; int main(void){ //freopen("in", "r", stdin); int x,y,j, i; char map[20][20]; /* while(scanf("%d", &n)){ for(i = 0; i < kind[n]; i++){ memset(map, 1, sizeof(map)); map[1][10] = '*'; for(j = 0; j < 4; j++){ x = 1 + gox[n][i][j]; y = 10 + goy[n][i][j]; map[x][y] = '*'; } for(j = 1; j <= 5; j++){ for(int k = 5; k <= 15; k++){ printf("%c",map[j][k]); } printf(" "); } printf(" "); } }* / for(n = 1; n <=6; n ++){ // while(scanf("%d", &n) != EOF){ m = 60/n; ans = 0; row = 0; dlx.init(72); for(i = 0; i < 12; i++){ for(j = 0; j < kind[i]; j++){ for(x=1; x <= n; x++){ for(y = 1; y <= m; y++){ color(i,j,x,y); } } } } dlx.dfs(); dabiao[i] = ans; printf("%d %d ",n, ans / 4); } return 0; } */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int ans[10] = {0, 0, 0, 2, 368, 1010, 2339}; int main(){ int n, m; while(cin>>n>>m){ if( n > m) swap(n, m); cout<<ans[n]<<endl; } return 0; }
HDU 3156 Repair Depots
题意:给出n 个点 (1 <= n <= 16),浮点坐标。在平面上找出c个点,以他们为圆心半径为r的c个圆可以覆盖n个点,求半径r的最小值
做法。二分半径。
两两枚举两个点,并获得建立圆心的信息。对于点X(x, y), X'(xx, yy)
如果其距离== r 则在其中间建圆心。
<r 则可以建出两个圆心(使X, Y恰好在圆上)
注意要给每个点的位置也建一个圆心。
输出%f才过。。。多输几位好像不对? 不知道是我写错了还是题目看错了。。。不贴代码了免得误导orz