2017年騰訊秋招軟件開發筆試編程題回憶版node
(全部題目大體描述以下,並不是完整的題目回憶,但意思大體同樣)ios
一、又一個魔法城市,城市裏面有n個魔法城堡,序號爲0,1,2。。。n-1;魔法城堡之間都有路徑相連;魔法城堡兩兩之間的到達的距離不一樣,所以所需時間也可能不會相同。如魔法城堡0到魔法城堡2須要耗時4小時;現,小明想從魔法城堡0到魔法城堡1,他想知道須要花費多少時間;爲了快速到達,有一魔法掃把,魔法掃把使用次數有限,使用一次,能夠將某一段間的時間減半;求小明從魔法城堡0到魔法城堡1花費的最小時間,精確到一位小數。編程
輸入:總共n+1行;spa
第一行,魔法城堡數n;魔法掃把可以使用的次數k;調試
第二行到第n行爲魔法城堡之間到達須要的時間;blog
輸出:從魔法城堡0到魔法城堡花費的最短期:t,精確到小數點後一位。排序
示例:ci
輸入:開發
3 2字符串
094
904
440
(注:騰訊這裏輸入的094,904,440,是以字符串的形式輸入的)
輸出:
4.0
我的大體思路:
利用Dijkstra最短路徑求法;記錄到魔法城堡1的最短路徑上每個前驅節點和對應的距離;而後對每段的距離進行降序排序;以後把魔法掃把使用在所耗時最多的段中。如0到1的最短路徑爲0到2,消耗爲4;2到1消耗爲3;魔法掃把能使用1次;那麼把這一次機會使用在0到2這一段路徑上;那麼最後最短期即爲:2+3=5.0;
代碼實現爲:
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <cstring>
#include <math.h>
#include <algorithm>
using namespace std;
#define MIN 99999
vector<int> dijkstra_shortpath(vector<vector<int>> arcs, int ednode)
{
int size = arcs.size();
vector<int> dist(size); //保存當前最短路徑
vector<int> path(size); //保存前驅節點
vector<int> S(size); //保存已經找到最短路徑的節點
//初始化
for (size_t i = 0; i < size; i++)
{
dist[i] = arcs[0][i];
S[i] = 0;
path[i] = 0;
}
S[0] = 1, path[0] = -1;
//進行循環更新每次遍歷每一個節點的最短路徑長度
for (int i = 1; i < size; i++)
{
int nmin = MIN, mi = 1;
for (int j = 1; j < size; j++)
{
if (!S[j] && dist[j] < nmin)
{
mi = j;
nmin = dist[j];
}
}
cout << "min index=" << mi << "; paht="<<nmin << endl;
S[mi] = 1;
//更新每一個節點的最短路徑長度
for (int j = 1; j < size; j++)
{
if (!S[j] && dist[mi] + arcs[mi][j] < dist[j])
{
dist[j] = dist[mi] + arcs[mi][j];
path[j] = mi; //保存節點j最短路徑的前驅mi
}
}
}
//輸出每一個節點的
for (int i = 0; i < size; i++)
{
cout << "[pre=" << path[i] << ",len=" << dist[i] << "]; ";
}
cout << endl;
vector<int> res;
while (path[ednode] != -1)
{
res.push_back(arcs[path[ednode]][ednode]);
cout << "[pre=" << path[ednode] << ";len=" << arcs[path[ednode]][ednode] << "];";
ednode = path[ednode];
}
cout << endl;
return res;
}
int main(int argc,char **argv)
{
int n = 0, k = 0;
vector<int> res;
while (cin >> n>>k)
{
vector<vector<int>> nodes;
string path;
for (int i = 0; i < n; i++)
{
cin >> path;
vector<int> node(n);
for (int i = 0; i < n; i++)
node[i] = path.at(i) - '0';
nodes.push_back(node);
}
res = dijkstra_shortpath(nodes, 1);
sort(res.begin(), res.end());//默認是升序遍歷
int sum = 0;
for (int i = res.size() - 1; i >= 0; i--)
{
if (k > 0)
{
sum += res[i] / 2;
k -= 1;
}
else sum += res[i];
}
cout << "min cost time=" << sum << endl;
}
return 0;
}
運行效果下圖所示:
二、小明有不少枚硬幣,每一枚銀幣的面值均爲2的k次方,而且該類硬幣的數量均爲2枚;也便是他的硬幣的序列是:1,1,2,2,4,4,8,8。。。;如今他去超市買東西,須要支付總額爲n;問他有多少種支付方式,也便是有多少種硬幣的組合的和爲n;(騰訊給的示例,想不起來了)
我的大體思路是:利用圖的深度優先遍從來作這道到,該過程得出的結果確定有一部分結果是重複的,則須要去重;暫時未想到其餘很好的辦法。
代碼實現以下:
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <cstring>
#include <math.h>
#include <algorithm>
using namespace std;
vector<int> res;
int get_cnt(int depth, int cur_sum, int target, set<vector<int>>& sres)
{
if (cur_sum == target)
{
vector<int> tmp;
for (int i = 0; i < res.size(); i++)
{
tmp.push_back(res[i]);
cout << res[i] << ", ";
}
cout << endl;
sres.insert(tmp);
return 1;
}
if (cur_sum > target ) return 0;
for (int i = depth; i < target * 2; i++)
{
cur_sum += pow(2, (i / 2));
res.push_back(pow(2, (i / 2)));
//cout << "push tms = " << i << "; sum = " << cur_sum << endl;
get_cnt(i + 1, cur_sum, target, sres) ? 1 : 0;
res.pop_back();
cur_sum -= pow(2, (i / 2));
//cout << "popo tms = " << i << "; sum = " << cur_sum << endl;
}
return 0;
}
int main(int argc, char **argv)
{
int target = 0;
while (cin >> target)
{
set<vector<int>> sres;
get_cnt(0, 0, target, sres);
cout <<"set size = " << sres.size() << endl;
}
return 0;
}
運行效果下圖所示:(注:set size,即爲組合狀況數)
三、這道編程大致大體是這麼描述的,有一臺魔法機器,機器上有兩個按鈕;機器的運算方式是:一次輸入兩個數字;兩個數字根據按下不一樣的進行同時進行相同的操做。規則以下:紅色按鈕:按下則兩個數,分別同時加1;藍色按鈕按下:兩個數分別同時*2。如今小明想知道,他有兩個數,和與之對應的目標數,分別記爲a,b,A,B;通過多少次按鈕操做可以把a變成A;的同時b變成B;輸出按鈕操做的最少次數;若是不能則輸出-1。
示例輸入:
100 1000 202 2002
輸出:
2
代碼大體以下,正確性很難講:
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <cstring>
#include <math.h>
#include <algorithm>
using namespace std;
int get_opera_cnt(int a, int A)
{
int cnt = 0;
if (A % 2 == 1) //把它變成偶數
{
A -= 1; //表示紅色按鈕按一次
cnt += 1;
}
if (A / 2 >= a)
{
while (A % 2 == 0 && A / 2 >= a)
{
cnt += 1;
A = A / 2; //表示藍色按鈕按一次
}
cnt += (A - a);//表示紅色按鈕按(A-a)次
}
else
cnt += (A - a);//表示紅色按鈕按(A-a)次
return cnt;
}
int main(int argc, char **argv)
{
int a, b, A, B;
while (cin >> a >> b >> A >> B)
{
int acnt = get_opera_cnt(a, A);
int bcnt = get_opera_cnt(b, B);
cout << "acnt=" << acnt << "; bcnt=" << bcnt << "; opera tms=";
if (acnt == bcnt)cout << acnt << endl;
else cout << -1 << endl;
}
return 0;
}
運行結果以下:(本身調試用的,未按標準輸入輸出,自行更正)
(以上僅供交流,勿噴;本人在規定時間內,未寫出這幾道題的答案,(┬_┬)😞)