Microsoft 2017 Campus Hiring Contest - April

1497 : Queen Attack

簡單過分不記了...

1498 : Diligent Robots

Description
There are N jobs to be finished. It takes a robot 1 hour to finish one job.
At the beginning you have only one robot. Luckily a robot may build more robots identical to itself. It takes a robot Q hours to build another robot.
So what is the minimum number of hours to finish N jobs?
Note two or more robots working on the same job or building the same robot won't accelerate the progress.
Input
The first line contains 2 integers, N and Q.
For 70% of the data, 1 <= N <= 1000000
For 100% of the data, 1 <= N <= 1000000000000, 1 <= Q <= 1000
Output
The minimum number of hours.
Sample Input
10 1
Sample Output
5

思路分析

首先,如果要復制機器,就要盡早復制,因為盡早復制可以盡早投入生產。
我的糾結點在于,復制的最后一輪,會不會有一部分機器人在復制,其他機器人在工作?
通過嚴謹的證明說明是不會的。


因為我上面的證明里得到了“T>2qm”這個臨界條件,因此在代碼里可以直接使用。

AC代碼

//
// Created by Xue Li on 2017/4/11.
//

#include <iostream>

using namespace std;

int main(){
    int64_t n;
    int64_t q;
    cin >> n >> q;
    int64_t m = 1;
    int64_t r = 0;
    while(n > 2*m*q){
        m = m << 1;
        r++;
    }
    int64_t t = q*r + n/m;
    if (n % m != 0)
        t += 1;
    cout << t;

    return 0;
}

在網上搜了一下,只搜到兩三篇記錄此題的文章,如萌萌噠絮兒,設復制k輪機器人(全部復制),遍歷k,直到k增加而時間不降低為止。這種做法假設時間隨k的增加呈僅有一個最低點的凹曲線,且每輪一定會全部復制,不知這種做法是否有直觀的理由?而我一開始就陷入了理論證明,如果真的是比賽那時間可肯定不夠用了。

1499 : A Box of Coins

描述
Little Hi has a box which consists of 2xN cells as illustrated below.
+----+----+----+----+----+----+
| A1 | A2 | A3 | A4 | .. | AN |
+----+----+----+----+----+----+
| B1 | B2 | B3 | B4 | .. | BN |
+----+----+----+----+----+----+
There are some coins in each cell. For the first row the amounts of coins are A1, A2, ... AN and for the second row the amounts are B1, B2, ... BN.
Each second Little Hi can pick one coin from a cell and put it into an adjacent cell. (Two cells are adjacent if they share a common side. For example, A1 and A2 are adjacent; A1 and B1 are adjacent; A1 and B2 are not adjacent.)
Now Little Hi wants that each cell has equal number of coins by moving the coins. He wants to know the minimum number of seconds he needs to accomplish it.
輸入
The first line contains an integer, N. 2 <= N <= 100000
Then follows N lines. Each line contains 2 integers Ai and Bi. (0 <= Ai, Bi <= 2000000000)
It is guaranteed that the total amount of coins in the box is no more than 2000000000 and is a multiple of 2N.
輸出
The minimum number of seconds.
樣例輸入
2
3 4
6 7
樣例輸出
4

問題分析:

最優策略:從左往右,先對上下兩個數字進行調整,然后不符合要求的部分跟右邊的調整。
道理在于,一個格子不符合要求的話,必須從相鄰的格子要或者給相鄰的格子,而對于上下格子,距離一定是1,也就是最小的成本了,所以優先考慮上下換。然后再考慮左右換,這是迫不得已了。
而這題我交的時候一直WA,很郁悶,然后點開了討論區,看到這個帖子,感覺醍醐灌頂,又感覺被打了一巴掌。。。


不知道這么蠢的人是不是只有我和樓主兩個 TAT

AC代碼

//
// Created by Xue Li on 2017/4/11.
//
#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

int64_t min(int64_t a, int64_t b){
    if (a <= b)
        return a;
    else
        return b;
}

int main(){
    int64_t n;
    cin >> n;
    vector<int64_t > A;
    vector<int64_t > B;
    int64_t sum = 0;
    for (int i = 0; i < n; i++){
        int64_t a, b;
        cin >> a >> b;
        sum += a;
        sum += b;
        A.push_back(a);
        B.push_back(b);
    }
    int64_t avg = (sum) / (2*n);
    int64_t move = 0;
    for (int i = 0; i < n; i++){
        //上下解決
        int64_t delta = 0;
        if (A[i] < avg && B[i] > avg){
            delta = min(avg - A[i], B[i] - avg);
            A[i] += delta;
            B[i] -= delta;
        }
        else if(A[i] > avg && B[i] < avg){
            delta = min(A[i] - avg, avg - B[i]);
            A[i] -= delta;
            B[i] += delta;
        }
        move += delta;
        //缺的就跟右邊要
        delta = A[i] - avg;
        A[i+1] += delta;
        A[i] = avg;
        move += abs(delta);
        delta = B[i] - avg;
        B[i] = avg;
        B[i+1] += delta;
        move += abs(delta);
    }
    cout << move;
    return 0;
}

1500 : EL SUENO

描述
In a video game, Little Hi is going to assassinate the leader of an evil group, EL SUENO.
There are N high-value targets in the group, numbered from 1 to N. Each target has another target as his direct superior except for EL SUENO who has no superior. So the superior-subordinate hierarchy forms a tree-like structure. EL SUENO is at the root.

The cost of assassinating the i-th target is Ci. Before assassinating a target Little Hi has to obtain enough information about him. For the i-th target, Little Hi needs INi units of information. By assassinating a target Little Hi will obtain some information about the target's direct superior. More specifically, the i-th target has IPi units of information about his superior. So in order to assassinate EL SUENO, Little Hi needs to assassinate some of his direct subordinates so that the sum of information obtained is enough; assassinating the subordinates needs to assassinate their direct subordinates ... until it reaches some targets require zero information in advance. (Luckily if a target has no subordinate he always requires zero information.)
How Little Hi wants to know what is the minimum cost for successful assassinating EL SUENO.
輸入
The first line contains an integer N.
Then follow N lines. Each line describes a target with 4 integers, Fi, INi, IPi, Ci.
Fi is i-th target's superior. For EL SUENO his Fi is zero.
INi is the amount of information needed to assassinate the i-th target. For a target has no subordinates his INi is always zero.
IPi is the amount of information the i-th target has about his superior Fi.
Ci is the cost of assassinating the i-th target.
For 30% of the data, 1 <= N <= 10, 0 <= INi, IPi <= 100
For 60% of the data, 1 <= N <= 100, 0 <= INi, IPi <= 1000
For 100% of the data, 1 <= N <= 2000, 0 <= Fi <= N, 0 <= INi, IPi <= 20000, 1 <= Ci <= 1000.
It is guaranteed that the N targets form a tree structure.
輸出
The minimum cost. If Little Hi is not able to assassinate EL SUENO output a number -1.
樣例輸入
6
2 1 2 2
0 4 0 2
2 0 2 5
2 0 2 6
1 0 1 2
1 0 1 3
樣例輸出
11

問題分析

題目的本質是動態規劃解0-1背包問題,自底向上地對各個節點做這件事。
我老自稱愛做動規題,結果今天竟想不起來0-1背包用動規怎么解了,真是打臉TAT,還有就是自己寫代碼真是太慢了,而且還容易出寫的問題,還是需要多加鍛煉啊,要寫得又快又準才好呢!

AC代碼

//
// Created by Xue Li on 2017/4/11.
//


#include <iostream>
#include <vector>

using namespace std;

/*動態規劃解0-1背包問題:
 * 從所有target中移除某些節點,保證剩余ip之和不小于superior的in,從而減小總cost,
 * 也就相當于選擇一些節點,保證ip之和小于in的余量(所有target的ip之和減去superior的in),最大化cost之和。
 *
 * information的余量作為包重量的限制;
 * 每個target的ip作為物品重量;
 * 每個target的cost作為物品價值;
 */
int zero_one(int n, vector<int> cost, vector<int> inf){
    int max_cost = 0;
    int max_inf = 0;
    int len = inf.size()-1;
    for (int i = 1; i <= len; i++)
        max_inf += inf[i];
    for (int i = 1; i <= len; i++)
        max_cost += cost[i];
    if (max_inf < n)
        return -1;
    if (max_inf == n)
        return max_cost;

    int inf_lmt = max_inf - n;
    vector<vector<int>> dp(len + 1, vector<int>(inf_lmt+1));
    for (int j = 0; j < inf_lmt+1; j++)
        dp[0][j] = 0;
    for(int i = 0; i < len+1; i++)
        dp[i][0] = 0;
    for (int i = 1; i <= len; i++){
        for (int j = 1; j <= inf_lmt; j++){
            dp[i][j] = dp[i-1][j];
            if ((j >= inf[i]) && ((dp[i-1][j-inf[i]] + cost[i]) > dp[i][j]))
                dp[i][j] = dp[i-1][j-inf[i]] + cost[i];
        }
    }
    return max_cost - dp[len][inf_lmt];
}

//相當于一個自底向上的過程,先處理完某node的所有下屬node,然后處理這個node
int oneNode(int num, int in, vector<vector<int>>& child, vector<int>& p_cost, vector<vector<int>>& targets){
    //這里主要是想希望下標從1開始,所以前面加了一個填充數
    vector<int> inf = {0};
    vector<int> cost = {0};
    for (int i = 0; i < child[num].size(); i++){
        int c = child[num][i];
        if (p_cost[c] < 0){
            oneNode(c, targets[c][1], child, p_cost, targets);
        }
        if (p_cost[c] >= 0) {
            cost.push_back(p_cost[c]);
            inf.push_back(targets[c][2]);
        }
    }
    int branch = zero_one(in, cost, inf);
    p_cost[num] = branch;
    if (branch < 0)
        return branch;
    p_cost[num] += targets[num][3];
    return p_cost[num];
}

int main(){
    int n;
    cin >> n;
    int root = 0;
    vector<vector<int>> targets(n+1, vector<int>(4));
    vector<vector<int>> child(n+1);
    vector<int> cost(n+1, -1);
    for (int i = 1; i <= n; i++){
        child[i] = {};
    }
    for (int i = 1; i <= n; i++){
        int f, in, ip, c;
        cin >> f >> in >> ip >> c;
        targets[i][0] = f;
        targets[i][1] = in;
        targets[i][2] = ip;
        targets[i][3] = c;

        if (in == 0) {
            cost[i] = c;
        }
        child[f].push_back(i);
        if (f == 0)
            root = i;
    }

    int rst = oneNode(root, targets[root][1], child, cost, targets);

    cout << rst;
    return 0;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 軍訓贊一一寫給二十二中2016級孩子 斷去秀發棄綺羅, 銘記校訓守公約。 烈日灼空膚色變, 稚軀挺拔汗成河。 迷彩...
    弦子之歌閱讀 196評論 0 1
  • 我屬于每晚都會做夢的那一類人。早上起來第一件事就是躺在床上細細回想夢境,然后……一不小心就又睡著了……夢其實是人類...
    Bunbun_Ly閱讀 1,476評論 5 11
  • 話語里包藏著真心 所以一句話 也帶有體溫 所以哪怕是一句話 在這冷酷的世界中 讓人維持生存的體溫 能夠活下去的 不...
    只是要張圖片閱讀 695評論 0 0