引言:比较简略,还请见谅!能力有限,难免有错,敬请不吝指导 ^_^ ~
比赛链接:http://acm.swjtu.edu.cn/JudgeOnline/showcontest?contest_id=1131
比赛对象:大一、大二
比赛时间:2012年11月18日 12:00——17:00
参考题解:
【A题:推箱子】
对箱子进行广搜,判断箱子的当前状态是否合法,判断合法的方式是,判断人能否从原状态到达箱子的“后面”。
测试数据:
输入
22 6 4 0 0 0 1 0 0 0 0 2 4 0 0 0 1 1 1 0 0 0 0 3 0 0 0 6 5 0 0 0 0 0 0 4 0 2 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 3 0 0 0 0 0 5 6 0 0 0 0 0 0 2 1 1 0 0 0 1 0 0 0 0 0 0 1 0 1 1 0 1 0 4 0 0 3 7 5 1 1 4 1 0 0 0 1 1 2 1 0 0 0 3 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 0 0 0 6 6 0 4 1 0 0 0 0 2 0 0 0 0 1 0 1 0 1 1 0 0 1 0 3 0 1 0 0 0 0 0 0 0 0 0 0 0 5 6 0 0 0 3 0 0 1 4 0 1 0 1 2 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 6 6 0 0 0 0 1 0 0 4 0 1 0 0 0 0 0 1 0 0 0 0 1 0 2 0 0 1 0 0 3 0 0 0 1 0 0 0 6 6 0 0 0 0 1 0 0 2 0 1 0 0 0 0 0 1 0 0 0 0 1 0 4 0 0 1 0 0 3 0 0 0 1 0 0 0 5 3 4 0 0 0 0 0 2 0 0 0 0 0 0 0 3 5 3 4 0 0 0 0 2 0 0 0 0 0 0 0 0 3 5 3 4 2 0 0 0 1 1 1 0 1 0 0 3 0 0 5 3 0 1 0 0 0 4 2 0 0 0 0 1 3 1 0 6 6 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 4 0 0 0 0 0 6 6 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 3 0 0 0 0 0 6 6 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 4 2 3 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 6 6 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 3 2 4 0 0 0 1 0 0 0 0 0 1 0 0 6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 3 1 1 0 0 0 2 0 0 0 0 0 4 0 0 6 6 0 0 0 4 0 0 0 0 0 2 0 0 1 1 1 3 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 5 0 0 0 0 0 4 2 0 1 1 0 1 0 0 0 1 0 0 0 3 1 0 0 0 0 5 3 4 0 0 0 0 2 0 0 0 0 0 0 0 0 3 7 5 1 1 4 1 0 0 0 1 1 2 1 0 0 0 3 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 0 0 0 6 6 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 4 0 0 0 0 0
Case #1: 6 Case #2: -1 Case #3: 7 Case #4: 11 Case #5: 9 Case #6: 3 Case #7: -1 Case #8: -1 Case #9: 4 Case #10: -1 Case #11: -1 Case #12: 4 Case #13: 8 Case #14: 2 Case #15: 1 Case #16: 1 Case #17: 1 Case #18: 1 Case #19: 5 Case #20: -1 Case #21: 11 Case #22: 8
首先,通过给定的当前状态,判断是哪位棋手下;然后,去枚举判断每一位空位,判断是否可以赢得游戏。
测试数据:
输入:
11 _______________ _______________ _______________ __________b____ _________w_____ ______wbw______ ____bbwwbb_____ __bbwbwbbwb____ ___wwbbwbw_____ _bwwwwbwwwb____ _bwwwwbwbww____ ___wbbw_bbbw___ ____wbbb_______ ______bb_______ _______________ _______________ _______________ _______________ _______________ _______________ ___bbbb________ __w____________ __w____________ __w____________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ ________w______ _____w__b______ ____wbb_bbw____ _______wb______ ________w______ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ ________b______ _____wwwb______ _____wbbbb_____ _______wb______ ________w______ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ w______________ _w______w______ __b____b_______ ___b__b________ ___wb_b________ ___wb__________ __wbw_b________ __www__b_______ _______________ _______________ _______________ _______________ _______________ bbbbw__________ bbbbw__________ wwwwbw_________ ____wbw________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ _______________ ______w________ ______w________ ______w________ ______w________ _______________ _____b_________ ___b_b_b_______ _______________ _______________ _______________ _______________ _______________ _______________ ____w__________ _____w_________ ______w________ _______________ ________w______ _______________ _______________ _____b_________ ___bbbwb_______ _____b_________ _______________ _______________ _______________ _______________ _______________ ____________w__ _______________ __________w____ _________w_____ ________w______ _______________ _______________ _____b_________ ___bbbwb_______ _____b_________ _______________ _______________ _______________ _______________ _______________ _______________ ______b________ ______b________ _______________ ______b________ ___ww_w________ _______________ _______________ _______________ _______________ _______________ _______________ _______________
Case #1: Yes Case #2: No Case #3: No Case #4: Yes Case #5: No Case #6: Yes Case #7: No Case #8: No Case #9: Yes Case #10: Yes Case #11: No
枚举数字和运算符,计算是否存在某一数学表达式值为24即可,可通过回溯法求解。
测试数据:
输入
30 4 10 4 10 5 5 5 A 2 7 9 9 2 10 10 10 3 3 3 3 3 3 3 4 3 3 3 5 3 3 3 6 3 3 3 7 3 3 3 8 3 3 3 9 3 3 3 10 3 3 4 4 3 3 4 10 3 3 5 5 3 3 5 8 3 3 6 6 3 3 7 10 3 3 8 8 3 3 9 9 3 3 10 10 3 4 6 7 3 4 8 8 3 4 9 10 3 5 5 5 3 5 5 10 3 5 7 7 3 5 8 10 A A J J A 2 Q Q
Case #1: Yes Case #2: Yes Case #3: No Case #4: No Case #5: Yes Case #6: Yes Case #7: Yes Case #8: Yes Case #9: Yes Case #10: Yes Case #11: Yes Case #12: Yes Case #13: Yes Case #14: No Case #15: Yes Case #16: No Case #17: Yes Case #18: No Case #19: Yes Case #20: Yes Case #21: No Case #22: No Case #23: No Case #24: No Case #25: No Case #26: No Case #27: No Case #28: No Case #29: Yes Case #30: Yes
对于任意一个最优切割线,总可以通过平移或旋转得到一条经过某两点的切割线,而且这条切割线仍然是最优切割线。
#include<cstdio> #include<cstring> struct Point { int x, y; Point() {} Point(int _x, int _y) : x(_x), y(_y) {} inline void readin() { scanf("%d %d", &x, &y); } inline Point operator+(const Point &cp) const { return Point(x + cp.x, y + cp.y); } inline Point operator-(const Point &cp) const { return Point(x - cp.x, y - cp.y); } inline int operator*(const Point &cp) const { return x * cp.y - y * cp.x; } }; struct Line { Point s, e; Line() {} Line(Point _s, Point _e) : s(_s), e(_e) {} }; #define Segment Line int isIntersected(Line L, Segment S) { int a = (L.e - L.s) * (S.s - L.e); int b = (L.e - L.s) * (S.e - L.e); return (a * b <= 0); } const int maxN = 10 + 2; int N, K[maxN]; Point P[maxN][maxN]; int nS, Select[maxN]; int gao() { static Point H[maxN * maxN]; int nh = 0; for(int i = 0; i < nS; i++) for(int j = 0; j < K[ Select[i] ]; j++) H[nh ++] = P[ Select[i] ][ j ]; for(int i = 0; i < nh; i++) for(int j = i + 1; j < nh; j++) { int yes = 0; for(int k = 0; k < nS; k++) for(int r = 0; r < K[ Select[k] ]; r++) if( isIntersected(Line(H[i], H[j]), Line(P[Select[k]][r], P[Select[k]][(r + 1) % K[ Select[k] ]])) ) { yes ++; break; } if( yes == nS ) return 1; } return 0; } int main() { freopen("data.in", "r", stdin); freopen("data.out", "w", stdout); int idx = 0, nt; scanf("%d", &nt); while( (nt --) > 0 ) { scanf("%d", &N); for(int i = 0; i < N; i++) { scanf("%d", K + i); for(int j = 0; j < K[i]; j++) P[i][j].readin(); } int ans = 1, up = 0x1 << N; for(int i = 3; i < up; i++) { nS = 0; for(int j = 0; j < N; j++) if( i & (0x1 << j) ) Select[nS ++] = j; if( nS <= ans ) continue; if( gao() ) ans = nS; } printf("Case #%d: %d\n", ++ idx, ans); } return 0; }
树状数组,或线段树。
#include <vector> #include <map> #include <set> #include <deque> #include <stack> #include <bitset> #include <algorithm> #include <sstream> #include <iostream> #include <cstdio> #include <queue> #include <cmath> #include <cstdlib> #include <cstring> #include <ctime> #include <string> #include <cassert> typedef long long i64d; typedef unsigned long long i64u; using namespace std; template<class T> inline T cAbs(T x) { if( x < 0 ) return -x; return x; } template<class T> inline T cMax(T a, T b) { return a > b ? a : b; } template<class T> inline T cMin(T a, T b) { return a < b ? a : b; } const int maxN = 250000 + 10; const i64d Mod = 65536; i64d A[maxN]; int N, K; int C[65536 + 10]; int lowbit(int x) { return x & (-x); } void update(int pos, int val) { while( pos <= 65536 ) { C[pos] += val; pos += lowbit(pos); } } int query(int pos) { int sum = 0; while( pos > 0 ) { sum += C[pos]; pos -= lowbit(pos); } return sum; } int main() { freopen("data.in", "r", stdin); freopen("data.out", "w", stdout); i64d seed, mul, add; while( scanf("%lld %lld %lld", &seed, &mul, &add) == 3 ) { scanf("%d %d", &N, &K); A[0] = seed; for(int i = 1; i < N; i++) A[i] = (A[i - 1] * mul + add) % Mod; if( K == 1 ) { i64d ans = 0LL; for(int i = 0; i < N; i++) ans += A[i]; printf("%lld\n", ans); continue; } if( K == 2 ) { i64d ans = 0LL; for(int i = 1; i < N; i++) ans += min(A[i], A[i - 1]); printf("%lld\n", ans); continue; } // add 1 for(int i = 0; i < N; i++) A[i] += 1LL; memset(C, 0, sizeof(C)); int l, r, m, tot, tmp; i64d ans = 0LL; for(int i = 0; i < N; i++) { if( i < K - 1 ) update((int)A[i], 1); else { update((int)A[i], 1); l = 1; r = 65536; tmp = 0; while( l <= r ) { m = (l + r) >> 1; tot = query(m); if( tot >= ((K + 1) / 2) ) { r = m - 1; tmp = m; } else l = m + 1; } ans += tmp; update((int)A[i - K + 1], -1); } } printf("%lld\n", ans - (N - K + 1LL)); } return 0; }
源自浙大月赛,考虑所有子矩形,对于每个子矩形,计算方案数,然后求和。对于每个子矩形,三角形的顶点在矩形边界的格点上,利用锐角性质,通过余弦定理得到格点间的不等式关系。
【G题:又见A+B】
模拟题,没有模出来,可以考虑再模一下。
【H题:K-数组】
排序后,统计计数即可。
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<ctime> #include<cstdlib> using namespace std; const int maxN = 50000 + 2; int N, K; struct node { int val, idx; inline void in(int &_idx) { idx = _idx; scanf("%d", &val); } inline bool operator<(const node &s) const { if( val != s.val ) return val < s.val; return idx < s.idx; } }; node A[maxN]; int main() { freopen("data.in", "r", stdin); freopen("data.out", "w", stdout); int idx = 0, nt; scanf("%d", &nt); while( (nt --) > 0 ) { scanf("%d %d", &N, &K); for(int i = 0; i < N; i++) A[i].in(i); A[0].val %= K; for(int i = 1; i < N; i++) A[i].val = (A[i - 1].val + A[i].val) % K; sort(A, A + N); long long ans = 0; int preVal = 0, totVal = 1; for(int i = 0; i < N; i++) { if( preVal == A[i].val ) { ans += (long long)totVal; totVal ++; } else { preVal = A[i].val; totVal = 1; } } cout << "Case #" << ++idx << ": " << ans << endl; } return 0; }
穷举法,这里放有几组输入数据的P值保留到小数点后面2位,似乎并不影响解答试题。
#include<cstdio> #include<cstring> int main() { freopen("data.in", "r", stdin); freopen("data.out", "w", stdout); int idx = 0, nt;scanf("%d", &nt); while( (nt --) > 0 ) { int X, Y; double P; double ans = 0.0; scanf("%d %d %lf", &X, &Y, &P); for(int i = 0; i <= X; i ++) for(int j = 0; j <= Y; j++) { double cmp = 0.0; if( j ) cmp += P * j / (i + j); if( Y - j ) cmp += (1.0 - P) * (Y - j) / (X - i + Y - j); if( cmp > ans ) ans = cmp; } printf("Case #%d: %.2lf\n", ++idx, ans); } return 0; }
输入
30 1 1 0.5 1 1 0.0 0 0 0 0 1 0 0 1 1 10 10 0.1 100 100 0.1 100 100 0.0 100 100 0.2 100 100 0.3 100 100 0.4 100 100 0.5 100 100 0.6 100 100 0.7 100 100 0.8 100 100 0.9 56 92 0.3 14 19 0.7 20 4 0.3 12 31 0.8 56 65 0.1 65 21 0.7 13 12 0.5 16 15 0.55 10 12 0.6 32 71 0.23 31 31 0.5 31 31 0.9 17 81 0.42 61 57 0.33
Case #1: 0.50 Case #2: 1.00 Case #3: 0.00 Case #4: 1.00 Case #5: 1.00 Case #6: 0.95 Case #7: 0.95 Case #8: 1.00 Case #9: 0.90 Case #10: 0.85 Case #11: 0.80 Case #12: 0.75 Case #13: 0.80 Case #14: 0.85 Case #15: 0.90 Case #16: 0.95 Case #17: 0.89 Case #18: 0.87 Case #19: 0.74 Case #20: 0.94 Case #21: 0.95 Case #22: 0.77 Case #23: 0.73 Case #24: 0.76 Case #25: 0.81 Case #26: 0.93 Case #27: 0.75 Case #28: 0.95 Case #29: 0.93 Case #30: 0.83
P.S. 测试数据难免会有差错,敬请指正!个人不推荐短时间内希望得到测试数据,一定程度上,不能提高个人能力。