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\n", ans[i].x, ans[i].y);}}else printf("No solution\n");printf("\n");}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 0x3f3f3f3fint 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? '\n' : ' ');}}else printf("-1\n");}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\n", 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\n", 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 0x3f3f3f3fbool 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\n", 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\n", 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 0x3f3f3f3fint 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("!!\n");ans = ida;dlx.dfs(0);printf("%d\n", 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\n", (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("\n"); } } 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\n", num[i]); maxn = unique(num+1, num+1+maxn)-num;// printf("%d\n", 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\n", 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 0000 0 0 0000 000 0 0********{1,2,2,2}, {1,2,2,2}, {0,0,1,2}, {0,0,1,2}},{ /******00000 00000 ********{0,0,0,0},{1,2,3,4}},{ /******00000 ********{1, 1, 1, 2}},{ /******0 0 000 00 00000 0 0 0 000 00********{0,1,1,1},{0,0,1,1},{0,1,2,2},{0,1,2,2}},{ /******0 00 0000 00000 0 0 00 00 00********{1,1,1,1}, {0,1,2,3},{0,0,0,1},{1,2,3,3},/******00 00000 0 0 00 0 0000 00 00********{0,0,0,1},{0,1,2,3},{1,1,1,1},{1,2,3,3}},{/******0 00 00 000 00 00 0000 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 00000 00 0 0 0000 0 0 000 00 00 00 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 00000 0 000 00 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 000 000 00 000 00 000 00 00000 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 00 0 000 000000 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 00000 00 00 00 000 00 00 0000 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 000 00 000 0 00 00 000 00 00 0 000 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 0000 0 0 0000 000 0 0******** /{0,0,1,2}, {0,-2,-1,0}, {1,2,2,2}, {1,2,0,0}},{ /******00000 00000 ******** /{1,2,3,4},{0,0,0,0}},{ /******00000 ******** / {-1,0,1,0}},{ /******0 0 000 00 00000 0 0 0 000 00******** /{2,0,1,2},{1,2,0,2},{1,0,0,1},{1,1,0,1}},{ /******0 00 0000 00000 0 0 00 00 00******** /{0,1,2,3},{1,0,0,0},{1,2,3,3}, {0,0,-1,0},/******00 00000 0 0 00 0 0000 00 00******** /{1,2,3,0},{1,1,1,1},{-3,-2,-1,0},{0,0,0,1}},{/******0 00 00 000 00 00 0000 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 00000 00 0 0 0000 0 0 000 00 00 00 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 00000 0 000 00 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 000 000 00 000 00 000 00 00000 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 00 0 000 000000 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 00000 00 00 00 000 00 00 0000 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 000 00 000 0 00 00 000 00 00 0 000 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("\n");}printf("\n");}}* /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",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