1. 程式人生 > >Codeforces Round #417 (Div. 2)

Codeforces Round #417 (Div. 2)

n) close gif 分享 else eve int fda src

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; }
View Code

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;
}
View Code

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;
}
View Code

D. Sagheer and Kindergarten(上完課補)

暫時沒看題意

E. Sagheer and Apple Tree dfs+博弈

E題的題意大概是,有一個蘋果樹,每個枝幹上有a_i個蘋果,Alice與Bob一起做遊戲。

Alice和Bob可以選擇下列操作中的一項,否則就輸了

1、如果當前節點為葉子節點,可以把該節點上的一個非空的蘋果集合吃掉。

2、如果當前節點不是葉子節點,可以把該節點上的一個非空的蘋果集合移動到它的兒子節點。

問你如果Alice可以交換兩個節點的蘋果的數量,那麽有多少種交換方法可以使他先手必勝?

這個題就是一個樹上的階梯博弈(根據lls的啟發),也就是一個傳統的Nim博弈。

(上完課補)

Codeforces Round #417 (Div. 2)