Codeforces Round #417 (Div. 2)
A. Sagheer and Crossroads 枚举
#include <bits/stdc++.h> using namespace std; typedef long long int LL; const int MAXN = 100005; int n; int a[4][4]; int main() { int flag = 0; for(int i = 0; i < 4; i++) { for(int j = 0; j < 4; j++) scanf("%d", &a[i][j]); if(a[i][3] && (a[i][1] || a[i][2] || a[i][0])) flag = 1; } if(a[0][3] && (a[3][2] || a[2][1] || a[1][0])) flag = 1; if(a[1][3] && (a[0][2] || a[3][1] || a[2][0])) flag = 1; if(a[2][3] && (a[1][2] || a[0][1] || a[3][0])) flag = 1; if(a[3][3] && (a[2][2] || a[1][1] || a[0][0])) flag = 1; if(flag) printf("YES\n"); else printf("NO\n"); return 0; }
B. Sagheer, the Hausmeister 暴搜
B题的意思大概是,有个人要从左下角的楼梯口开始走,把整栋楼的灯关闭需要最小的步数。
他可以从左边的楼梯->关闭整层的灯->返回左边的楼梯
也可以从左边的楼梯->关闭整层的灯->到达右边的楼梯
同样可以讨论右边的楼梯
当然如果整层楼没有灯可以关闭,他可以直接上一层
如果整栋楼没有灯可以关闭,他就可以结束了
#include <bits/stdc++.h> using namespace std; typedef long long int LL; const int MAXN = 100005; char s[20][105]; int star = 0, ans = MAXN; int num[20], n, m; void dfs(int left, int i, int step, int gg) { if(step > ans || i < 0) return; if(num[i]) { if(left) { int now = 0; for(int j = 1; j <= m; j++) { if(s[i][j] == '1') now++; if(now == num[i]) { gg += now; if(i == 0 || gg == star) { ans = min(ans, step + j); return; }else { dfs(left, i-1, step + j*2 + 1, gg); dfs(left^1, i-1, step + m + 2, gg); } break; } } }else { int now = 0; for(int j = 1; j <= m; j++) { if(s[i][m+1-j] == '1') now++; if(now == num[i]) { gg += now; //printf("%d %d %d\n", left, i, j); if(i == 0 || gg == star) { ans = min(ans, step + j); return; }else { dfs(left^1, i-1, step + m + 2, gg); dfs(left, i-1, step + j*2 + 1, gg); } break; } } } }else return dfs(left, i-1, step+1, gg); } int main() { scanf("%d%d", &n, &m); for(int i = 0; i < n; i++) scanf("%s", s[i]); for(int i = 0; i < n; i++) { num[i] = 0; for(int j = 0; j < m + 2; j++) { if(s[i][j] == '1') num[i]++, star++; } } if(star == 0) return 0*printf("0\n"); dfs(1, n-1, 0, 0); printf("%d\n", ans); return 0; }
C. Sagheer and Nubian Market 二分+排序
C的题意大概是,有个要要购买商品,他购买商品的价格与商品的价格和他购买物品的数量有关。
如果这个物品起初的下标是xi,价格是a_xi, 同时他总共购买k个物品的话,这个物品的价格是 a_xi + k*xi
问你购买商品不超过S元,最多能买几个物品,最少花费多少钱
二分物品的数量,然后更新每个物品的价格, 排序
#include <bits/stdc++.h> using namespace std; typedef long long int LL; const int MAXN = 100005; int a[MAXN], n, S; LL s[MAXN]; LL slove(int mid) { for(int i = 0; i < n; i++) s[i] = 1LL*(i+1)*mid + a[i]; sort(s, s+n); LL sum = 0; for(int i = 0; i < mid; i++) sum += s[i]; return sum; } int main() { scanf("%d%d", &n, &S); for(int i = 0; i < n; i++) scanf("%d", &a[i]); int l = 0, r = n, mid; while(l < r) { mid = (l + r + 1)>>1; if(slove(mid) <= 1LL*S) l = mid; else r = mid - 1; } if(l == 0) printf("0 0\n"); else printf("%d %lld\n", l, slove(l)); return 0; }
D. Sagheer and Kindergarten(上完课补)
暂时没看题意
E. Sagheer and Apple Tree dfs+博弈
E题的题意大概是,有一个苹果树,每个枝干上有a_i个苹果,Alice与Bob一起做游戏。
Alice和Bob可以选择下列操作中的一项,否则就输了
1、如果当前节点为叶子节点,可以把该节点上的一个非空的苹果集合吃掉。
2、如果当前节点不是叶子节点,可以把该节点上的一个非空的苹果集合移动到它的儿子节点。
问你如果Alice可以交换两个节点的苹果的数量,那么有多少种交换方法可以使他先手必胜?
这个题就是一个树上的阶梯博弈(根据lls的启发),也就是一个传统的Nim博弈。
(上完课补)