【TopCoder】SRM 680 DIV 2
1. BearPair之bigDistance
1.1 题目概述
在 <= 50的字符串中找位置i,j 满足
(1) s[i] != s[j];
(2) abs(i-j)尽可能大。
若不存在返回-1, 否则返回最大值。
1.2 基本思路
没什么好说的,串长这么短 O(n^2)直接A了。
1.3 代码
1 class BearPair { 2 public: 3 int pos[26]; 4 5 int bigDistance(string s) { 6 int len = s.length(); 7 int mx = -1; 8 9 rep(i, 0, len) { 10 rep(j, 0, len) { 11 if (s[j]==s[i]) 12 continue; 13 14 mx = max(mx, abs(j-i)); 15 } 16 } 17 18 return mx; 19 } 20 };
2. BearChairs之findPositions
2.1 题目描述
一家餐馆,椅子排成一行从1开始,足够长,有N个元素的数组atLeast表示第i个顾客希望他的椅子编号大于等于atLeast[i]。
同时,需要保证任意两个顾客的椅子间相隔至少为d,并且顾客最终得到的椅子编号越小越好。这里,顾客的请求是有序的。
求最终的椅子编号。
2.2 基本思路
基本想法是贪心,第k个顾客最好的可能性是得到atLeast[k]编号的椅子。
如果此时该顾客与前k-1个顾客的间隔都大于等于d,那么答案就是atLeast[k]。
假设不满足,如果我们可以使前k-1个顾客的椅子编号按升序排列,那么当answer[j]-d<answer[k] && answer[k]<answer[j]+d
时,下一个最优的候选项即为answer[j]+d,而该候选项一定满足answer[1..j]。仅需判断其是否满足answer[j+1..k-1]即可。
因此,使用set维护已经确定的最优位置,即可解。
2.3 代码
1 class BearChairs { 2 public: 3 static const int maxn = 1005; 4 5 vi findPositions(vi vc, int d) { 6 int sz = SZ(vc), tmp; 7 vi ret; 8 sti st; 9 sti::iterator iter; 10 11 rep(i, 0, sz) { 12 int pos = vc[i]; 13 for (iter=st.begin(); iter!=st.end(); ++iter) { 14 tmp = *iter; 15 if (tmp-d<pos && pos<tmp+d) { 16 pos = tmp + d; 17 } 18 } 19 20 ret.pb(pos); 21 st.insert(pos); 22 } 23 24 return ret; 25 } 26 27 };
2.4 数据发生器
1 import sys 2 import string 3 from random import randint 4 5 6 def GenData(fileName): 7 with open(fileName, "w") as fout: 8 t = 1 9 bound = 10**6 10 # fout.write("%d\n" % (t)) 11 for tt in xrange(t): 12 n = randint(1, 1000) 13 atLeast = [] 14 for i in xrange(n): 15 x = randint(1, bound) 16 atLeast.append(x) 17 fout.write(" ".join(map(str, atLeast)) + "\n") 18 d = randint(1, 10**6) 19 fout.write("%d\n" % (d)) 20 21 22 def MovData(srcFileName, desFileName): 23 with open(srcFileName, "r") as fin: 24 lines = fin.readlines() 25 with open(desFileName, "w") as fout: 26 fout.write("".join(lines)) 27 28 29 def CompData(): 30 print "comp" 31 srcFileName = "F:\Qt_prj\hdoj\data.out" 32 desFileName = "F:\workspace\cpp_hdoj\data.out" 33 srcLines = [] 34 desLines = [] 35 with open(srcFileName, "r") as fin: 36 srcLines = fin.readlines() 37 with open(desFileName, "r") as fin: 38 desLines = fin.readlines() 39 n = min(len(srcLines), len(desLines))-1 40 for i in xrange(n): 41 ans2 = int(desLines[i]) 42 ans1 = int(srcLines[i]) 43 if ans1 > ans2: 44 print "%d: wrong" % i 45 46 47 if __name__ == "__main__": 48 srcFileName = "F:\Qt_prj\hdoj\data.in" 49 desFileName = "F:\workspace\cpp_hdoj\data.in" 50 GenData(srcFileName) 51 MovData(srcFileName, desFileName) 52 53
3. BearFair2之isFair
3.1 题目描述
有一个包含n(n%3 == 0)个元素的集合,其中的元素都在[1,b]区间,其中mod3等于0、1、2的元素个数均为n/3。
现有两个长度均为q数组upTo, quantity表示集合中的元素在区间[1, upTo[i]]的数目为quantity[i]。
判定是否存在这样一个集合满足upTo和quantity。
其中upTo的元素在[1,b]区间内,quantity的元素在[1,n]区间内,b在区间[1,1000]内。
3.2 基本思路
这是一个判定问题,首先以upTo作为first, quantity作为second重新构建pair数组,排序后,可以做初步的剪枝。
但仍需进一步判定是否存在这样的集合。基本思路是网络流,难点是如何构建图。
对pair树组的每个结点编号1001...1001+q-1
对1..b编号为1...b
对%3==0作结点mod0
对%3==1作结点mod1
对%3==2作结点mod2
可以这样建图:
1)st对pair结点建边,容量为对应的quantity[i]-quantity[i-1];
2)pair结点对它包含的区间中的每个结点建边,容量为1;
3)编号1..b对其对应的modx建边,容量为1;
4)modx对ed建边,容量为n/3。
需要注意pair数组可能没有覆盖[1,b],对余下的区间仍需要建边,与上述类似。
然后,判定最大流是否为n即可。
使用Dinic解该网络流。
3.3 代码
1 class BearFair2 { 2 3 typedef struct { 4 int v, f, nxt; 5 } edge_t; 6 7 public: 8 static const int INF = 0x3f3f3f3f; 9 static const int maxv = 1100; 10 static const int maxe = 1e5+5; 11 static const int st = maxv - 1; 12 static const int ed = maxv - 2; 13 static const int mod0 = maxv - 3; 14 static const int mod1 = maxv - 4; 15 static const int mod2 = maxv - 5; 16 17 int head_[maxv]; 18 int head[maxv], l; 19 int Q[maxv]; 20 int dis[maxv]; 21 edge_t E[maxe]; 22 int n, b; 23 24 void init() { 25 memset(head, -1, sizeof(head)); 26 l = 0; 27 } 28 29 void addEdge(int u, int v, int c) { 30 E[l].v = v; 31 E[l].f = c; 32 E[l].nxt = head[u]; 33 head[u] = l++; 34 35 E[l].v = u; 36 E[l].f = 0; 37 E[l].nxt = head[v]; 38 head[v] = l++; 39 } 40 41 bool bfs() { 42 int l = 0, r = 0; 43 int u, v, k; 44 45 memset(dis, 0, sizeof(dis)); 46 Q[r++] = st; 47 dis[st] = 1; 48 49 while (l < r) { 50 u = Q[l++]; 51 for (k=head[u]; k!=-1; k=E[k].nxt) { 52 v = E[k].v; 53 if (E[k].f && !dis[v]) { 54 dis[v] = dis[u] + 1; 55 if (v == ed) 56 return false; 57 Q[r++] = v; 58 } 59 } 60 } 61 62 return true; 63 } 64 65 int dfs(int u, int val) { 66 if (val==0 || u==ed) 67 return val; 68 69 int ret = 0, tmp; 70 int v; 71 72 for (int& k=head_[u]; k!=-1; k=E[k].nxt) { 73 v = E[k].v; 74 if (E[k].f && dis[v]==dis[u]+1 && (tmp=dfs(v, min(val, E[k].f)))>0) { 75 ret += tmp; 76 val -= tmp; 77 E[k].f -= tmp; 78 E[k^1].f += tmp; 79 if (val == 0) 80 break; 81 } 82 } 83 84 return ret; 85 } 86 87 int Dinic() { 88 int ret = 0, tmp; 89 90 while (1) { 91 if (bfs()) 92 break; 93 94 memcpy(head_, head, sizeof(head)); 95 while (1) { 96 tmp = dfs(st, INF); 97 if (tmp == 0) 98 break; 99 ret += tmp; 100 } 101 } 102 103 return ret; 104 } 105 106 string isFair(int n, int b, vector <int> upTo, vector <int> quan) { 107 this->n = n; 108 this->b = b; 109 init(); 110 111 vpii vp; 112 int sz = SZ(upTo); 113 114 rep(i, 0, sz) { 115 vp.pb(mp(upTo[i], quan[i])); 116 } 117 118 sort(all(vp)); 119 rep(i, 0, sz) { 120 if (vp[i].sec > vp[i].sec) 121 return "unfair"; 122 123 if (i && vp[i].sec<vp[i-1].sec) 124 return "unfair"; 125 126 if (i && vp[i].fir==vp[i-1].fir && vp[i].sec!=vp[i-1].sec) 127 return "unfair"; 128 } 129 130 int fr = 1, pm = 0; 131 132 rep(i, 0, sz) { 133 addEdge(st, 1001+i, vp[i].sec-pm); 134 while (fr <= vp[i].fir) { 135 addEdge(1001+i, fr, 1); 136 ++fr; 137 } 138 pm = vp[i].sec; 139 } 140 141 if (fr <= b) { 142 addEdge(st, 1001+sz, n-pm); 143 while (fr <= b) { 144 addEdge(1001+sz, fr, 1); 145 ++fr; 146 } 147 } 148 149 for (int i=1; i<=b; i+=3) 150 addEdge(i, mod1, 1); 151 for (int i=2; i<=b; i+=3) 152 addEdge(i, mod2, 1); 153 for (int i=3; i<=b; i+=3) 154 addEdge(i, mod0, 1); 155 156 addEdge(mod0, ed, n/3); 157 addEdge(mod1, ed, n/3); 158 addEdge(mod2, ed, n/3); 159 160 int flow = 0; 161 162 flow = Dinic(); 163 if (flow == n) 164 return "fair"; 165 else 166 return "unfair"; 167 } 168 };
3.4 数据发生器
1 import sys 2 import string 3 from random import randint 4 5 6 def GenData(fileName): 7 with open(fileName, "w") as fout: 8 t = 1 9 bound = 10**6 10 # fout.write("%d\n" % (t)) 11 for tt in xrange(t): 12 n = randint(1, 16) * 3 13 b = randint(1, n) 14 fout.write("%d %d\n" % (n, b)) 15 q = randint(1, 50) 16 upTo = [] 17 for i in xrange(q): 18 x = randint(1, b) 19 upTo.append(x) 20 fout.write(" ".join(map(str, upTo)) + "\n") 21 quantity = [] 22 for i in xrange(q): 23 x = randint(0, n) 24 quantity.append(x) 25 fout.write(" ".join(map(str, quantity)) + "\n") 26 27 28 def MovData(srcFileName, desFileName): 29 with open(srcFileName, "r") as fin: 30 lines = fin.readlines() 31 with open(desFileName, "w") as fout: 32 fout.write("".join(lines)) 33 34 35 def CompData(): 36 print "comp" 37 srcFileName = "F:\Qt_prj\hdoj\data.out" 38 desFileName = "F:\workspace\cpp_hdoj\data.out" 39 srcLines = [] 40 desLines = [] 41 with open(srcFileName, "r") as fin: 42 srcLines = fin.readlines() 43 with open(desFileName, "r") as fin: 44 desLines = fin.readlines() 45 n = min(len(srcLines), len(desLines))-1 46 for i in xrange(n): 47 ans2 = int(desLines[i]) 48 ans1 = int(srcLines[i]) 49 if ans1 > ans2: 50 print "%d: wrong" % i 51 52 53 if __name__ == "__main__": 54 srcFileName = "F:\Qt_prj\hdoj\data.in" 55 desFileName = "F:\workspace\cpp_hdoj\data.in" 56 GenData(srcFileName) 57 MovData(srcFileName, desFileName) 58 59