腾讯笔试编程题交流

第一题

给出一个n个节点的无向图,所有节点之间都有通路,通路的权值都是0-9,起点在0号节点,目标是1号节点。有一个附加条件,你可以使k条边的权值减半,求最短路径。


解法来自大佬

dp[i][j][k]表示当前在i要走j步到1,还可以使用k次魔法,然后j从0到n-1 dp

第二题

你有很多硬币,面额为1,2,4,8,....,2^k,每种面额的硬币有两个,要求凑出n元来,输出不同的凑硬币方案的数目。


动态规划,下面代码是从评论的大佬重总结的。

// dp[i][j] 表示从最低的二进制位到第 i 位,j = 0 表示不能进位,j = 1 表示可以进位的方案数
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
ll n;
ll dp[100][2];

int main(void) {
    ll n;
    while (cin >> n) {
        memset(dp, 0, sizeof(dp));
        dp[0][0] = 1;
        dp[0][1] = 1;
        if (n & 1) dp[0][1] = 0;

        for (int i = 1; i <= 60; ++ i) {
            if (n & (1LL<<i)) {
                dp[i][0] += dp[i - 1][0];
                dp[i][0] += dp[i - 1][1];

                dp[i][1] += dp[i - 1][1];
            } else {
                dp[i][0] += dp[i - 1][0];

                dp[i][1] += dp[i - 1][0];
                dp[i][1] += dp[i - 1][1];
            }
        }
        cout << dp[60][0] << endl;
    }
    return 0;
}

第三题

输入4个数,a,b,A,B,可以对a,b进行两种操作,同时加一,或者乘2.
目标是使a==A,b==B,输出操作的最小次数。


下面代码是我和同学讨论之后得出的最优解了。

int method1(int a,int b,int A,int B){
    if(a>A || b>B) return -1;
    int c = a-b,
        d = A-B;
    if(c*d < 0) return -1;
    if(c==0 && d==0){
        // ok 
    }else if(c!=0 && d!=0){
        if(d%c!=0) return -1;
        int e = d/c;
        if(e&(e-1)!=0) return -1;
    }else return -1;
    int res = 0;
    while(true){
        if(A==a) return res;
        if(A%2==0){
            if(A/2>=a){
                A>>=1;
                res++;
            }else{
                res += A-a;
                return res;
            }
        }else{
            A-=1;
            res++;
        }
    }
}
#腾讯#
全部评论
第二题我的思路是类似于有序数组求合为定值的思路。小于的话较小数>>1,大于的话较大数<<1,等于的话counter+1...时间太紧张了不知道对不对
点赞 回复 分享
发布于 2017-09-13 16:57
// 第二个硬币问题,如果有错误,欢迎指正。 // dp[i][j] 表示从最低的二进制位到第 i 位,j = 0 表示无进位,j = 1 表示有进位的方案数 #include <bits/stdc++.h> using namespace std; using ll = long long; ll n; ll dp[100][2]; int main(void) { ll n; while (cin >> n) { memset(dp, 0, sizeof(dp)); dp[0][0] = 1; dp[0][1] = 1; if (n & 1) dp[0][1] = 0; for (int i = 1; i <= 60; ++ i) { if (n & (1LL<<i)) { dp[i][0] += dp[i - 1][0]; dp[i][0] += dp[i - 1][1]; dp[i][1] += dp[i - 1][1]; } else { dp[i][0] += dp[i - 1][0]; dp[i][1] += dp[i - 1][0]; dp[i][1] += dp[i - 1][1]; } } cout << dp[60][0] << endl; } return 0; } 第三题,我是直接贪心,从上往下不断的砍。。 #include <bits/stdc++.h> using namespace std; int main(void) { int a, b, A, B; while (cin >> a >> b >> A >> B) { bool flag = true; int ans = 0; while (A > a && B > b) { if (A % 2 == 0 && B % 2 == 0) { A /= 2; B /= 2; } else if (A % 2 == 1 && B % 2 == 1) { -- A; -- B; } else { flag = false; break; } ++ ans; } if (flag && A == a && B == b) cout << ans << endl; else cout << -1 << endl; } return 0; }
点赞 回复 分享
发布于 2017-09-13 17:00
第三题,我的思路是化成二进制比较不同的位数,试了几个过了但是不知道对不对-。-
点赞 回复 分享
发布于 2017-09-13 17:07
我只想笑😂
点赞 回复 分享
发布于 2017-09-13 16:56
不是说5点结束吗,4点40多就提示时间到了,刚好写完第一道题目后面两道都没看
点赞 回复 分享
发布于 2017-09-13 16:58
第一个跑的dfs 第三个,log(A - B) / (a - b)就是2的个数?,A - a * (A - B)/(a - b)为多项式部分然后再求1的个数?
点赞 回复 分享
发布于 2017-09-13 16:58
同第一题战略性放弃
点赞 回复 分享
发布于 2017-09-13 16:58
第三题也就只能DFS了吧(菜鸟轻喷)……  可能DFS到累加阶段能够直接加,不需要多次迭代了。。 我也就想到这一个优化的点。。 但是没时间了
点赞 回复 分享
发布于 2017-09-13 16:59
哎呀差不多
点赞 回复 分享
发布于 2017-09-13 17:00
战略性放弃。。。( ̄▽ ̄)"
点赞 回复 分享
发布于 2017-09-13 17:01
都是疯狂dfs,魔法王国那道暴力估计超时
点赞 回复 分享
发布于 2017-09-13 17:01
硬币那道题我是第一题。。。想着是拿动态规划做,大家帮我看看,为什么min_num就是不变呢==我觉得我逻辑没问题啊ORZ #include <iostream> using namespace std; void find_equal(int num1,int num2,int n,int total1,int total2,int &min_num){   if(num1==total1&&num2==total2){     if(n<min_num)       min_num=n;     return;   }   if(num1>total1)     return;   n=n+1;   find_equal(num1*2,num2*2,n,total1,total2,min_num);   find_equal(num1+1,num2*2,n,total1,total2,min_num); } int main() {     int a,b,A,B;   while(cin >> a >> b>>A>>B){     int min_num=100000;     find_equal(a,b,0,A,B,min_num);     if(min_num!=100000)       cout<<min_num<<endl;     else       cout<<"-1"<<endl;   } }
点赞 回复 分享
发布于 2017-09-13 17:01
第三题倒着推。 A是偶数则除以2,A是奇数则减一。  B同时操作。最后判断A==a B==b
点赞 回复 分享
发布于 2017-09-13 17:02
最短路那个我是dp[i][j][k]表示i到j用掉k次扫把的最短路径,然后跑floyd 最小次数那个就是普通的bfs应该没啥问题... 硬币是第一题手贱跳过去了...感觉是按二进制位的1和0找找规律统计一下...?
点赞 回复 分享
发布于 2017-09-13 17:02
看了大佬们的思路 我感觉自己真蠢 (sad
点赞 回复 分享
发布于 2017-09-13 17:04
第一题dp[i][j][k]表示当前在i要走j步到1,还可以使用k次魔法,然后j从0到n-1 dp 第二题猜的 n/2,如果n是2的k次方,答案再加1,理由是看成求n可以表示成多少种两个数的和 第三题没时间
点赞 回复 分享
发布于 2017-09-13 17:07
魔法王国DFS,机器那题我是直接贪心 从后面不断/2 然后再-1
点赞 回复 分享
发布于 2017-09-13 17:13
看到战略性放弃笑了
点赞 回复 分享
发布于 2017-09-13 17:17
//硬币问题 转化为二进制 //对于(7)111这类只有一种解法 //对于111.1000.0连续n个1,m个0的共有n * m +1种解法 //然后把二进制串分为x个连续的(11.100.0) //最左的一个(11.100.0) ans[0] = n0 * m0 +1; //先计算最右边两个 (11.100.0)(11.100.0),设有n1个1,m1个0;n0个1,m0个0,那么有 // ans[1] = (n1*m1+1)* (n0*m0+1) + m0中解法; //然后再和左边一个10串计算ans[2] = (n2*m2+1)* ans[1] + m1*ans[0]+ m0; //从优向左依次计算 #include<iostream> #include<vector> #include<algorithm> using namespace std; int main() { unsigned long long n; while(cin >> n) { vector<int> num; long long onezero[30][2]; long long ans[30]; while(n) { num.push_back( n & 1); n = n >> 1; } // for(int i = num.size()-1; i >=0; --i) // { // cout <<num[i]; // } // cout <<endl; int pair01 = 0; int cnt0 = 0; int cnt1 = 0; bool flag; while((flag = num.front())&& !num.empty()) { num.erase(num.begin()); } if(num.empty()) { cout << 1 <<endl; } else { for(int i = 0; i < num.size(); ++i) { if(num[i] == 1) { if(!flag) { onezero[pair01][0] = cnt0; cnt0 = 0; flag = true; } ++cnt1; if( i == num.size()-1) { onezero[pair01][1] = cnt1; } } else { if(flag) { onezero[pair01++][1] = cnt1; cnt1 = 0; flag = false; } ++cnt0; } } ans[0] = onezero[0][1] * onezero[0][0] +1; for(int k = 1; k <= pair01; ++k) { int join = onezero[0][0]; for(int j = 1; j < k; ++j) { join += onezero[j][0] * ans[j-1]; } ans[k] = (onezero[k][1] * onezero[k][0] +1) * ans[k-1] + join; } cout << ans[pair01]<<endl; } } return 0; }
点赞 回复 分享
发布于 2017-09-14 00:55

相关推荐

头像
10-09 19:35
门头沟学院 Java
洛必不可达:java的竞争激烈程度是其他任何岗位的10到20倍
点赞 评论 收藏
分享
头像
09-16 12:33
拐儿中学 Java
希希睿:我都忘了我是来找工作的了😂就看你们皮
点赞 评论 收藏
分享
身边的人都在收获,我却还在原地踏步,到底该怎么办啊!每次看到他们的好消息,我都想放弃,心里不停地问自己:到底该怎么才能找到一份工作呢?这种无力感让我想要彻底摆烂,真的很想知道,别人是怎么做到的。有没有人分享一下经历呢?我想学习一下啊走出这样的日子。
鼗:秋招其实是运气>实力的一场竞技游戏,除非实力很强(学历和技术)。大多数人都是半斤八两,看面试官和HR以及简历被曝光的概率罢了,有些时候你可能运气差一点或者说面试官不太友好也或者说你确实准备的不够好之类的,这些都是可能发生的事情。我觉得能做的事情是不比较、不气馁、在面试前多看一点面试的时间冷静一点自信一点,大大方方面试,给自己多一点时间去求职。我这样说不是站着说话不腰疼,我是想说你的offer还在路上,你也值得在这些困难之后得到你较为理想的offer,请你继续加油,保持乐观,积极打败你现在的困难
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务