http://codeforces.com/contest/676
在allzysyz学弟和hqwhqwhq的邀请下,打了我的第三场CF。。。
毕竟在半夜。。所以本来想水到12点就去睡觉的。。。结果一下次过了三题,发现第四题是个bfs,就打到了12:30.。。。BC貌似是没有了,不知道后面还会不会有,最近就打CF为主吧。。
A题:
http://codeforces.com/problemset/problem/676/A
应该算是比较水吧。没有什么坑点。直接枚举最大值在最左最右侧和最小值在最左最右侧四种情况。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <map> #include <queue> #include <vector> #include <string> #define LL long long using namespace std; int main() { //freopen("test.in", "r", stdin); //freopen("test.out", "w", stdout); int n, t, indexone, indexn; while (scanf("%d", &n) != EOF) { for (int i = 0; i < n; ++i) { scanf("%d", &t); if (t == 1) indexone = i; if (t == n) indexn = i; } printf("%d ", max(max(indexone, n-1-indexone), max(indexn, n-1-indexn))); } return 0; }
B题:
http://codeforces.com/problemset/problem/676/B
是ccpc热身赛一题的简化版,首先我可以把所有的酒强行先倒入第一杯,然后让它一层一层往下流。暴力模拟一遍就可以了。上一层的第i杯,会流入下一层的第i杯和第i+1杯。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <map> #include <queue> #include <vector> #include <string> #define LL long long using namespace std; double a[2][10000]; int main() { //freopen("test.in", "r", stdin); //freopen("test.out", "w", stdout); int n, t, ans; double tmp; while (scanf("%d%d", &n, &t) != EOF) { bool flag; ans = 0; a[1][1] = t; for (int i = 1; i <= n; ++i) { memset(a[(i+1)%2], 0, sizeof(a[(i+1)%2])); flag = true; for (int j = 1; j <= i; ++j) { if (a[i%2][j] >= 1) { tmp = a[i%2][j]-1; ans++; a[(i+1)%2][j] += tmp/2.0; a[(i+1)%2][j+1] += tmp/2.0; flag = false; } } if (flag) break; } printf("%d ", ans); } return 0; }
C题:
http://codeforces.com/problemset/problem/676/C
当时比较直接的想法就先求出把前i段都变成同样字符的代价的所有前缀和suma, sumb。这样就可以求解任意区间变成同样字符的代价了。
然后枚举区间左值,二分区间右值。就可以求解了。这样的复杂度是nlogn。
但是考虑到区间右值其实具有单调性。于是我可以从后往前遍历区间左值,那么区间右值要么不变,要么是上一次的位置往前移动。于是用两个指针就可以2n时间内完成了。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <map> #include <queue> #include <vector> #include <string> #define LL long long using namespace std; const int maxN = 100005; int n, k; int suma[maxN], sumb[maxN]; char str[maxN]; void input() { scanf("%s", str); suma[0] = sumb[0] = 0; for (int i = 0; i < n; ++i) { if (str[i] == 'a') { suma[i+1] = suma[i]; sumb[i+1] = sumb[i]+1; } else { suma[i+1] = suma[i]+1; sumb[i+1] = sumb[i]; } } } int getLen(int from) { int ans, lt = from, rt = n, mid; while (lt+1 < rt) { mid = (lt+rt)>>1; if (suma[mid]-suma[from-1] > k) rt = mid; else lt = mid; } if (suma[rt]-suma[from-1] <= k) ans = rt-from+1; else ans = lt-from+1; lt = from; rt = n; while (lt+1 < rt) { mid = (lt+rt)>>1; if (sumb[mid]-sumb[from-1] > k) rt = mid; else lt = mid; } if (sumb[rt]-sumb[from-1] <= k) ans = max(ans, rt-from+1); else ans = max(ans, lt-from+1); return ans; } void work() { int ans = 0; for (int i = 1; i <= n; ++i) ans = max(ans, getLen(i)); printf("%d ", ans); } int main() { //freopen("test.in", "r", stdin); //freopen("test.out", "w", stdout); while (scanf("%d%d", &n, &k) != EOF) { input(); work(); } return 0; }
D题:
http://codeforces.com/problemset/problem/676/D
这题是个bfs,比较容易看出来。首先我设置一个二进制状态1111,四位,最高位表示上方有门,第二位表示右方有门,第一位表示下方有门,最低位第0位表示左方有门。
然后写个swtich,把map中所有的字符映射到二进制状态。
然后就是bfs了。
bfs带有三个状态x,y,state。x和y即坐标,state表示经过了几次旋转。
然后就是瞎几把搜了。。。
第一种情况(state+1)%4
第二种情况便是上下左右搜,代码我是直接复制粘贴,所以只看往上的情况。
首先这种状态下必须上方有门,而且上面的格子下方有门。
对于上方有门,由于是顺时针旋转,也就是mp的映射二进制位最高位在逆时针旋转后是1。而这个逆时针旋转就是(3+state)%4这一位了。代码里可以看出来。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <algorithm> #include <set> #include <map> #include <queue> #include <vector> #include <string> #define LL long long using namespace std; //up right down left int get(char ch) { switch (ch) { case '+': return 15; case '-': return 5; case '|': return 10; case '^': return 8; case '>': return 4; case '<': return 1; case 'v': return 2; case 'L': return 14; case 'R': return 11; case 'U': return 7; case 'D': return 13; case '*': return 0; } } bool judge(int p, int index) { for (int i = 0; i < index; ++i) p >>= 1; return p&1; } const int maxN = 1005; int n, m, fromx, fromy, tox, toy; char mp[maxN][maxN]; int s[maxN][maxN][5]; void input() { memset(mp, '*', sizeof(mp)); memset(s, -1, sizeof(s)); for (int i = 1; i <= n; ++i) { scanf("%s", mp[i]+1); mp[i][m+1] = '*'; } scanf("%d%d", &fromx, &fromy); scanf("%d%d", &tox, &toy); } struct node { int x, y; int state; }; int myMin(int x, int y) { if (x == -1) return y; if (y == -1) return x; return min(x, y); } void work() { node t, k; queue<node> q; t.x = fromx; t.y = fromy; t.state = 0; s[t.x][t.y][t.state] = 0; q.push(t); while (!q.empty()) { t = q.front(); q.pop(); k = t; k.state = (k.state+1)%4; if (s[k.x][k.y][k.state] == -1) { s[k.x][k.y][k.state] = s[t.x][t.y][t.state]+1; q.push(k); } int dir1, dir2; dir1 = get(mp[t.x][t.y]); //up if (judge(dir1, ((3+t.state)%4+4)%4)) { dir2 = get(mp[t.x-1][t.y]); if (judge(dir2, ((1+t.state)%4+4)%4)) { k.x = t.x-1; k.y = t.y; k.state = t.state; if (s[k.x][k.y][k.state] == -1) { s[k.x][k.y][k.state] = s[t.x][t.y][t.state]+1; q.push(k); } } } //right if (judge(dir1, ((2+t.state)%4+4)%4)) { dir2 = get(mp[t.x][t.y+1]); if (judge(dir2, ((0+t.state)%4+4)%4)) { k.x = t.x; k.y = t.y+1; k.state = t.state; if (s[k.x][k.y][k.state] == -1) { s[k.x][k.y][k.state] = s[t.x][t.y][t.state]+1; q.push(k); } } } //down if (judge(dir1, ((1+t.state)%4+4)%4)) { dir2 = get(mp[t.x+1][t.y]); if (judge(dir2, ((3+t.state)%4+4)%4)) { k.x = t.x+1; k.y = t.y; k.state = t.state; if (s[k.x][k.y][k.state] == -1) { s[k.x][k.y][k.state] = s[t.x][t.y][t.state]+1; q.push(k); } } } //left if (judge(dir1, ((0+t.state)%4+4)%4)) { dir2 = get(mp[t.x][t.y-1]); if (judge(dir2, ((2+t.state)%4+4)%4)) { k.x = t.x; k.y = t.y-1; k.state = t.state; if (s[k.x][k.y][k.state] == -1) { s[k.x][k.y][k.state] = s[t.x][t.y][t.state]+1; q.push(k); } } } } int ans = -1; ans = myMin(ans, s[tox][toy][0]); ans = myMin(ans, s[tox][toy][1]); ans = myMin(ans, s[tox][toy][2]); ans = myMin(ans, s[tox][toy][3]); printf("%d ", ans); } int main() { //freopen("test.in", "r", stdin); //freopen("test.out", "w", stdout); while (scanf("%d%d", &n, &m) != EOF) { input(); work(); } return 0; }