1. 程式人生 > >騰訊2018秋招筆試真題(2)

騰訊2018秋招筆試真題(2)

騰訊2018秋招筆試真題

3、畫家小Q

【題目描述】畫家小 Q 又開始他的藝術創作。小 Q 拿出了一塊有 NxM 畫素格的畫板, 畫板初始狀態是空白
的,用’X’表示。
小 Q 有他獨特的繪畫技巧,每次小 Q 會選擇一條斜線, 如果斜線的方向形如’/’,即斜率為 1,小 Q 會選擇這
條斜線中的一段格子,都塗畫為藍色,用’B’表示;如果對角線的方向形如’\’,即斜率為-1,小 Q 會選擇這條
斜線中的一段格子,都塗畫為黃色,用’Y’表示。
如果一個格子既被藍色塗畫過又被黃色塗畫過,那麼這個格子就會變成綠色,用’G’表示。
小 Q 已經有想畫出的作品的樣子, 請你幫他計算一下他最少需要多少次操作完成這幅畫。
輸入描述:
每個輸入包含一個測試用例。
每個測試用例的第一行包含兩個正整數 N 和 M(1 <= N, M <= 50), 表示畫板的長寬。
接下來的 N 行包含 N 個長度為 M 的字串, 其中包含字元’B’,’Y’,’G’,’X’,分別表示藍色,黃色,綠色,空
白。整個表示小 Q 要完成的作品。
輸出描述:
輸出一個正整數, 表示小 Q 最少需要多少次操作完成繪畫。
輸入示例:
4 4
YXXB
XYGX
XBYY
BXXY
輸出示例:
3
說明:
XXXX
XXXX
XXXX
XXXX
->
YXXX
XYXX
XXYX
XXXY
->
YXXB
XYBX
XBYX
BXXY
->
YXXB
XYGX
XBYY
BXXY

解題思路:
從(0,0)位置開始遍歷

  • 如果遍歷到(i,j)位置為B——>則繼續向左下方(i+1,j-1)和右上方(i-1,j+1)
    遍歷時,遇到將B置為X,遇到G置為(消除B)置為Y
    count++;
  • 如果遍歷到(i,j)位置為Y——>則繼續向左上方(i-1,j-1)和右下方(i+1,j+1)
    遍歷時,遇到將Y置為X,遇到G置為(消除Y)置為B
    count++;
  • 如果遍歷到(i,j)位置為G——>則分別執行1,2
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class Main03 {
    static char[][] chs = new char[50][50];
    static int n;
    static int m;

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        n = in.nextInt();
        m = in.nextInt();
        for
(int i = 0; i < n; i++) { String str = in.next(); for(int j = 0; j < m; j++) { chs[i][j] = str.charAt(j); } } int count = 0; for(int i = 0; i < n; i++) { for(int j = 0; j < m; j++) { if(chs[i][j] == 'B') { dfs_B(i, j); count++; } else if(chs[i][j] == 'Y') { dfs_Y(i, j); count++; } else if(chs[i][j] == 'G') { dfs_B(i, j); count++; dfs_Y(i, j); count++; } } } System.out.println(count); } private static void dfs_B(int i, int j) { if(i >= 0 && i < n && j >= 0 && j < m && (chs[i][j] == 'B' || chs[i][j] == 'G')) { if(chs[i][j] == 'B') { chs[i][j] = 'X'; } else if(chs[i][j] == 'G'){ chs[i][j] = 'Y'; } dfs_B(i + 1, j - 1); dfs_B(i - 1, j + 1); } return ; } private static void dfs_Y(int i, int j) { if(i >= 0 && i < n && j >= 0 && j < m && (chs[i][j] == 'Y' || chs[i][j] == 'G')) { if(chs[i][j] == 'Y') { chs[i][j] = 'X'; } else if(chs[i][j] == 'G'){ chs[i][j] = 'B'; } dfs_Y(i - 1, j - 1); dfs_Y(i + 1, j + 1); } return ; } }

4、貪吃的小Q

【題目描述】小 Q 的父母要出差 N 天,走之前給小 Q 留下了 M 塊巧克力。小 Q 決定每天吃的巧克力數量不
少於前一天吃的一半,但是他又不想在父母回來之前的某一天沒有巧克力吃,請問他第一天最多能吃多少
塊巧克力
輸入描述:
每個輸入包含一個測試用例。
每 個 測 試 用 例 的 第 一 行 包 含 兩 個 正 整 數 , 表 示 父 母 出 差 的 天 數 N(N<=50000) 和 巧 克 力 的 數 量
M(N<=M<=100000)。
輸出描述:
輸出一個數表示小 Q 第一天最多能吃多少塊巧克力。
輸入示例:
3 7
輸出示例:
4

解題思路:
首先想到的是等比求和
首相為x是需要求的值,公比是1/2,一共有N項,滿足下列方程
x + 1/2*x + …… + (1/2)^(N-1)*x = M
(等比數列求和公式)變形為——>
x*(1-(1/2)^N) / (1-1/2) = M
x = M / (2 * (1-(1/2)^N))
x求的的值即為最大值
如果x不為整數需向下取整

public class Main04 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        int x = (int) Math.ceil((m / (2 * (1 - Math.pow(0.5, n)))));
        System.out.println(x);
    }
}

然後只過了20%,:joy:
估計是浮點數的表示範圍有限,在計算時資料有丟失
換策略
用二分查詢
1 <= x <= M
x每次取中間值,求出第一天吃的巧克力為當前值是需要的總共巧克力與M比較

import java.util.Scanner;

public class Main04_2 {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        int low = 1;
        int high = m;
        while(low < high) {
            int mid = (low + high + 1) >> 1;// /2
            int need = sum(n, mid);
            if(need > m) {
                high = mid - 1;
            } else if(need == m) {
                high = mid;
                break;
            } else {
                low = mid;
            }
        }
        System.out.println(high);
    }

    private static int sum(int n, int mid) {
        int need = 0;
        for(int i = 0; i < n; i++) {
            need += mid;
            mid = (mid + 1) >> 1; //不小於前一天的一半,向上取整
        }
        return need;
    }
}