贪心专题(不定期更新)
Posted 萌萌的美男子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了贪心专题(不定期更新)相关的知识,希望对你有一定的参考价值。
1、UVa 10382 - Watering Grass (贪心—区间覆盖)
题意:一块矩形草坪,给出若干个分布在中轴线上的喷水装置,喷水范围为圆形。问能否覆盖整个草坪,若能,求出最少的喷水装置数目。
思路:圆形半径小于等于草坪宽度一半的不用考虑;在剩下的喷水圆形区域中,求出对应覆盖草坪的矩形区块,之后则进行贪心处理:找出矩形区块[L,R]左侧L小于等于当前已覆盖区域的右侧POS的区块中,右侧R最大的那个,同时更新POS.
1 #include<iostream> 2 #include<cmath> 3 #include<algorithm> 4 using namespace std; 5 struct sprk 6 { 7 double r,ldis; 8 double L, R; 9 }v[10005]; 10 double n, l, w; 11 bool Cmp(const sprk& a, const sprk& b) 12 { 13 if (a.L < b.L) return true; 14 else if (a.L == b.L) 15 { 16 if (a.R < b.R) return true; 17 else return false; 18 } 19 else return false; 20 } 21 int main() 22 { 23 while (cin >> n >> l >> w) 24 { 25 int sz = 0; 26 sprk tmp; 27 for (int i = 0; i < n; i++) 28 { 29 cin >> tmp.ldis >> tmp.r; 30 if (tmp.r <=w/2.0) continue; 31 double tl = sqrt(tmp.r*tmp.r-w*w/4.0); 32 tmp.L = tmp.ldis*1.0 - tl; 33 tmp.R = tmp.ldis*1.0 + tl; 34 if (tmp.R < 0) continue; 35 v[sz++] = tmp; 36 } 37 sort(v, v+sz, Cmp); 38 int num = 0; 39 double pos = 0; 40 int k = 0; 41 bool ok = false; 42 if (sz>0&&v[0].L <= 0) 43 { 44 k = 0; 45 pos = 0; 46 while (k < sz) 47 { 48 int j = k; 49 double Rpos = pos; 50 while (j < sz&&v[j].L <= pos) 51 { 52 if (v[j].R > Rpos) Rpos = v[j].R; 53 ++j; 54 } 55 if (j == k)break; 56 num++; 57 pos = Rpos; 58 k = j; 59 if (pos >= l) 60 { 61 ok = true; 62 break; 63 } 64 } 65 } 66 if(ok) cout << num << endl; 67 else cout << -1 << endl; 68 } 69 return 0; 70 }
2、Uva10905 Children‘s Game
题意:给出若干个数字,把这些数字重新组合成一个新的数字,要求这个数字的字典序最大。
思路:用字符串保存;从大到小排序,关键为比较函数:把两个字符串按先后顺序重新组合成两个新的字符串,比较两个新字符串的字典序大小,字典序大的新字符串的第一个子字符串如果是传入比较函数的第一个参数,则为true,否则为false。
1 #include<iostream> 2 #include<string> 3 #include<string.h> 4 #include<algorithm> 5 using namespace std; 6 string s[55]; 7 int n; 8 bool Cmp(const string &a, const string &b) 9 { 10 string tmp1 = a + b; 11 string tmp2 = b + a; 12 if (tmp1 > tmp2) return true; 13 else return false; 14 } 15 int main() 16 { 17 while (cin >> n, n != 0) 18 { 19 for (int i = 0; i < n; i++) cin >> s[i]; 20 sort(s, s + n, Cmp); 21 for (int i = 0; i < n; i++) 22 { 23 cout << s[i]; 24 } 25 cout << endl; 26 } 27 return 0; 28 }
3、UVA 11134 Fabled Rooks
题意:给出n*n的棋盘,以及n个棋子的限制放置的矩形区域(给出左上顶点(xl,yl)和右下顶点的坐标(xr,yr))。要求每行每列只能有一个棋子。求任意一种方案,若无,则输出impossible
思路:分别对行和列进行贪心处理,贪心过程和第一题相似:对于行r(列c),找到xl≤r,xr≥r(yl≤c,yr≥c)且未被选取的棋子中,xr(yr)最小的那个,使其x(y)坐标为r(c).
1 #include<iostream> 2 #include<algorithm> 3 #include<memory.h> 4 using namespace std; 5 const int maxn = 5005; 6 struct node 7 { 8 int id; 9 int xl, yl, xr, yr; 10 int x, y; 11 }ch[maxn]; 12 bool vis[maxn]; 13 int n; 14 bool flag = true; 15 void CalX() 16 { 17 memset(vis, 0, sizeof(vis)); 18 int r = 1; 19 for (int i = 0; i < n; i++) 20 { 21 int minr = maxn; 22 int pos; 23 for (int j = 0; j < n; j++) 24 { 25 if (!vis[j] && ch[j].xl <= r&&ch[j].xr >= r&&ch[j].xr < minr) 26 { 27 minr = ch[j].xr; 28 pos = j; 29 } 30 } 31 if (minr == maxn) 32 { 33 flag = false; 34 return; 35 } 36 vis[pos] = true; 37 ch[pos].x = r; 38 r++; 39 } 40 } 41 void CalY() 42 { 43 memset(vis, 0, sizeof(vis)); 44 int c = 1; 45 for (int i = 0; i < n; i++) 46 { 47 int minc = maxn; 48 int pos; 49 for (int j = 0; j < n; j++) 50 { 51 if (!vis[j] && ch[j].yl <= c&&ch[j].yr >= c&&ch[j].yr < minc) 52 { 53 minc = ch[j].yr; 54 pos = j; 55 } 56 } 57 if (minc == maxn) 58 { 59 flag = false; 60 return; 61 } 62 vis[pos] = true; 63 ch[pos].y = c; 64 c++; 65 } 66 } 67 int main() 68 { 69 while (cin >> n, n != 0) 70 { 71 flag = true; 72 for (int i = 0; i < n; i++) 73 { 74 cin >> ch[i].xl >> ch[i].yl >> ch[i].xr >> ch[i].yr; 75 ch[i].id = i + 1; 76 } 77 CalX(); 78 if(flag) CalY(); 79 if (flag) 80 { 81 for (int i = 0; i < n; i++) 82 { 83 cout << ch[i].x << ‘ ‘ << ch[i].y << endl; 84 } 85 } 86 else cout << "IMPOSSIBLE\n"; 87 } 88 return 0; 89 }
以上是关于贪心专题(不定期更新)的主要内容,如果未能解决你的问题,请参考以下文章