騰訊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;
}
}