这两天主要是打比赛,然后补题,再根据复盘的不足之处去找题目训练。
1.CF一场加补题:2.航电杯,5小时比赛。
然后就是补题:
对于1003Backpack这个题目比较巧妙。01背包的题意,求得是在V刚好满足的情况下,所有W异或的最大值。一开始就考虑错了,没什么思路。看了题解才知道其实思路是很简单的,就是枚举最后所有异或值的情况,看看是不是能取到刚好的体积。就是我已经给你确定了最后的值,看你能不能把我的体积压到位。能就说明可以否则说明这个异或值取不到,最后去最大的即可。
假设输入v,w; 那么对于这个转移来说 dp[j] = max(dp[j], dp[j^w]) 这里的max就是 | 的意思,将dp[j^w]这个状态全部拿上, j^w 相当于再次异或就是没有拿,还要改变的是dp[j^w]这个状态对应的体积不是这个,而是出去后面大小为v 的空间的状态。(dp[j]里面都是一个1024位的bit,每一位代表空间1)那么出去后面v的空间就是dp[j] <<= v;
因此转移方程:全部移位 g[j] = dp[j]; g[j] <<= v; 之后转移dp[j] |= g[j ^ w];
#include#define OST ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); #define endl "n" using namespace std; const int N = 1030; bitset dp[N], g[N]; void solve() { int n, m; cin >> n >> m; for (int j = 0; j < 1024; ++j) { dp[j].reset(); } dp[0][0] = 1; for (int i = 1; i <= n; i++) { int v, w; cin >> v >> w; for (int j = 0; j < 1024; j++) { g[j] = dp[j]; g[j] <<= v; } for (int j = 0; j < 1024; j++) { dp[j] |= g[j ^ w]; } } int ans = -1; for (int i = 0; i < 1024; i++) { if (dp[i][m]) { ans = i; } } cout << ans << endl; } signed main() { int T = 1; cin >> T; while (T--) { solve(); } return 0; }
还有就是另外一道几何题目:
1009, Laser
#include3.其他刷题:using namespace std; const int N = 5e5 + 5; struct node { double x, y; }; node p[N]; int n; bool ok(node i, node j) { if (i.x == j.x || i.y == j.y || abs(i.x - j.x) == abs(i.y - j.y)) return true; return false; } bool check() { cin >> n; bool flag = false; for (int i = 1; i <= n; i++) { cin >> p[i].x >> p[i].y; } node a = p[1], b; vector ke; for (int i = 2; i <= n; i++) { if (ok(a, p[i])) continue; b = p[i]; // 两点不直接满足,枚举两点的交点12个 if (a.x > b.x) { node tmp = a; a = b; b = tmp; } double ba1 = (a.x + a.y) / 2; double ba2 = (a.y - a.x) / 2; double bb1 = (b.x + b.y) / 2; double bb2 = (b.y - b.x) / 2; // a 的水平线交 b的米字4线 ke.push_back({b.x, a.y}); ke.push_back({bb1 - a.y, a.y}); ke.push_back({a.y - bb2, a.y}); // a的竖直线交 b的米字4线 ke.push_back({a.x, b.y}); ke.push_back({a.x, -a.x + bb1}); ke.push_back({a.x, a.x + bb2}); // a的斜率为1的直线交b的米字四线 ke.push_back({b.x, b.x + ba2}); ke.push_back({b.y - ba2, b.y}); ke.push_back({(bb1 - ba2) / 2, (ba2 + bb1) / 2}); // a的斜率为-1的直线交b的米字四线 ke.push_back({b.x, -b.x + ba1}); ke.push_back({ba1 - b.y, b.y}); ke.push_back({(ba1 - bb2) / 2, (ba1 + bb2) / 2}); break; } if (ke.size() == 0) { flag = true; } else { for (int i = 0; i < 12; i++) { int kk = 1; for (int j = 1; j <= n; j++) { if (ok(ke[i], p[j])) continue; kk = 0; break; } if (kk) { flag = true; break; } } } return flag; } int main() { int T; cin >> T; while (T--) { if (check()) cout << "YES" << endl; else cout << "NO" << endl; } }



