Google Code Jam 2015资格赛

来源:互联网 发布:双11数据作假 编辑:程序博客网 时间:2024/05/22 17:28

题目在这里:https://code.google.com/codejam/contest/6224486/dashboard


有种资格赛一年比一年难的感觉,难道是我越来越弱了。。。。


A. Standing Ovation

注意到如果x是一个可行解的话,所有比x大的数都会是可行解,因此很自然的满足二分的要求。不过数据范围比较小,也可以从小到大进行暴力枚举,然后验证是否符合要求,找到的第一个数即为答案。

#include <bits/stdc++.h>#define FOR(i, n) for (int i = 0; i < n; ++i)using namespace std;int main() {    int N, mx;    string s;    cin >> N;    FOR(tt, N) {        cin >> mx >> s;        assert(s.size() == mx + 1);        int res = 0;        for (res = 0; res <= mx; ++res) {            int val = res + (s[0] - '0');            bool ok = true;            for (int i = 1; i <= mx; ++i) {                if (val >= i) {                    val += s[i] - '0';                    continue;                }                else {                    ok = false;                    break;                }            }            if (ok) { cout << "Case #" << tt + 1 << ": " << res << endl; break; }        }     }    return 0;}


B. Infinite House of Pancakes

这题用贪心来解,首先要明白:special minute排在前面所得到的解总不会比排在后面的得到的解差。原因很简单:special minute之后非空盘子的数目增多,每一分钟可以吃掉的蛋糕数也变多,更有利于尽快完成任务。

所以可以认为:先执行了x分钟的special minute操作,然后接下来全是吃蛋糕,花了y分钟,y肯定就等于最大的蛋糕体积。答案就应该是x + y

但是x和y的取值是多少呢?这个地方就需要一个枚举的过程来辅助,枚举y的值,对每一个y值,计算每一个蛋糕拆成不大于y的蛋糕所需要的时间,累加便得到x,最后取min(x + y)即可

#include <bits/stdc++.h>#define FOR(i, n) for (int i = 0; i < n; ++i)using namespace std;int main() {    int N, D;    vector<int> numbers;    cin >> N;    FOR(tt, N) {        cin >> D;        numbers.resize(D);        FOR(i, D) cin >> numbers[i];                int res = 1005, mx = *max_element(numbers.begin(), numbers.end());        // enumerate maximum number        for (int i = 1; i <= mx; ++i) {            int cur = 0;            FOR(j, numbers.size()) {                if (numbers[j] % i == 0) cur += numbers[j] / i - 1;                else cur += numbers[j] / i;            }            res = min(res, cur + i);        }        cout << "Case #" << tt + 1 << ": " << res << endl;    }    return 0;}


C. Dijkstra

跟图论毛线关系都没有。。google的人完全是标题党。。。


一个很自然的思路是把字符串构造出来,分别从左右两边进行扫描,但是字符串太长,内存和时间都不允许。假设a等于一个字符串运算的结果,那么a^4 = 1总成立,不管a的取值是什么,所以可以按照重复次数对4取模的余数进行分类,左右两侧只有4 * 4 = 16种可能的取值,对于每一种取值组合,只在一个字符串内部进行扫描,判断左侧能否计算出i,右侧能否计算出k。

#include <bits/stdc++.h>#define FOR(i, n) for (int i = 0; i < n; ++i)using namespace std;string multiply(const string& s1, const string& s2) {    assert(s1.size() <= 2 && s2.size() <= 2);    if (s1 == "1") return s2;    if (s2 == "1") return s1;    if (s1[0] == '-' && s2[0] == '-') return multiply(s1.substr(1, 1), s2.substr(1, 1));    if (s1[0] == '-') {        string t = multiply(s1.substr(1, 1), s2);        if (t[0] == '-') return t.substr(1, 1);        else return "-" + t;    }    if (s2[0] == '-') {        string t = multiply(s1, s2.substr(1, 1));        if (t[0] == '-') return t.substr(1, 1);        else return "-" + t;    }    assert(s1.size() == 1 && s2.size() == 1);    if (s1 == s2) return "-1";    if (s1 == "i" && s2 == "j") return "k";    if (s1 == "i" && s2 == "k") return "-j";    if (s1 == "j" && s2 == "k") return "i";    if (s1 == "j" && s2 == "i") return "-k";    if (s1 == "k" && s2 == "i") return "j";    if (s1 == "k" && s2 == "j") return "-i";    assert(false);    return "";}string spow(const string& number, long long p) {    if (p % 4 == 0) return "1";    if (p % 4 == 2) return multiply(number, number);    if (p % 4 == 1) return number;    else return multiply(number, multiply(number, number));}int main() {    int T, len;    long long repeat;    string s;    cin >> T;    FOR(tt, T) {        cout << "Case #" << tt + 1 << ": ";        cin >> len >> repeat;        cin >> s;                assert(len == s.size());        string res = "1";        FOR(i, s.size()) res = multiply(res, s.substr(i, 1));        // a necessary condition        if (spow(res, repeat) != "-1") {            cout << "NO" << endl;            continue;        }        bool solution = false;        FOR(i, 4) {            if (solution) break;            string left = spow(res, i);            bool ok = false;             int lidx = -1;            FOR(k, s.size()) {                if (ok || left == "i" || left == "-i") { ok = true; break; }                left = multiply(left, s.substr(k, 1));                if (left == "i" || left == "-i") {                    ok = true; lidx = k; break;                }            }            if (!ok || lidx == s.size() - 1) continue;            FOR(j, 4) {                if (solution) break;                string right = spow(res, j);                ok = false;                 int ridx = -1;                for (int k = s.size() - 1; k >= 0; --k) {                    if (ok || right == "k" || right == "-k") { ok = true; break; }                    right = multiply(s.substr(k, 1), right);                    if (right == "k" || right == "-k") {                        ok = true; ridx = k; break;                    }                }                if (!ok || ridx == 0) continue;                       int total = i + j;                assert(lidx != -1 || ridx != -1);                if (lidx == -1 && ridx != -1) ++total;                else if (lidx != -1 && ridx == -1) ++total;                            else if (lidx < ridx) ++total;                else if (lidx >= ridx) total += 2;                                if (repeat >= total) {                    solution = true;                    break;                }            }        }        if (solution) cout << "YES" << endl;        else cout << "NO" << endl;    }    return 0;}


D. Ominous Omino

这完全就是脑筋急转弯的题目。。。考的不是算法而是人的智商。。。


首先注意到,N >= 7是不可能有解的,题目中第二张图就说明了这个结论,中间那个空隙无论如何都是填充不进去的。

然后对N = 1, 2, 3, 4, 5, 6分别枚举,考虑哪些情况无解就可以了。N = 5的时候有一个不容易想的地方,就是5行3列的情形,


中间那个是不可能有解的,因为它把整个矩形分割成了两部分,上半部分不能够被5整除,无论怎么放都不行,囧。。。

import java.util.*;import java.io.*;/** * @author: kyc */public class D{    static int N, R, C;    public static void main(String ... orange) throws Exception    {        Scanner input = new Scanner(System.in);        int numCases = input.nextInt();        for (int n = 0; n < numCases; n++)        {            N = input.nextInt();            R = input.nextInt();            C = input.nextInt();            System.out.printf("Case #%d: %s\n", n + 1, good() ? "GABRIEL" : "RICHARD");        }    }    static boolean good()    {        if (R * C % N != 0)            return false;        if (N >= 7)            return false;        else if (N == 6)        {            if (Math.min(R, C) <= 3)                return false;        }        else if (N == 5)        {            if (Math.min(R, C) <= 2 ||                    Math.min(R, C) == 3 && Math.max(R, C) == 5)                return false;        }        else if (N == 4)        {            if (Math.min(R, C) <= 2)                return false;        }        else if (N == 3)        {            if (Math.min(R, C) <= 1)                return false;        }        return true;    }}


不管怎么说,资格赛肯定是水过去了。。。。神啊,求google code jam的T-shirt!



0 0
原创粉丝点击