C/C++方向试卷代码题杂烩(一)

代码题

1. 老板发奖金

老板一共需要给某个员工发奖金n元,可以选择一次发1元,也可以选择一次发2元,也可以选择一次发3元。请问老板给这位员工发放完n元奖金共有多少种不同的方法?
数据范围:1 <= n <= 10

需要注意,一次性最多只能发三块

是青蛙跳台阶的类似问题,类比青蛙跳台阶问题来说的话就是每次可以跳一步、或者两步、或者三步,求到n阶台阶有几种跳法。

循环求解
#
#
# @param num_money int整型 奖金的总数,单位为元
# @return int整型
#
class Solution:
    def CalulateMethodCount(self , num_money ):
        # write code here
        recur_add=0
        f=[0 for _ in range(num_money+1)]
         
        f[1]=1
        f[2]=2
        f[3]=4
         
        for i in range(4,num_money+1):
            f[i]=f[i-1]+f[i-2]+f[i-3]
             
        return f[num_money]
如果没有这个一次性最多只能发三块的限制

1:先发1块的情况下,剩下4块是不是就和发4块的方法一样了?
2:先发2块的情况下,剩下3块是不是就和发3块的方法一样了?
3:先发3块的情况下,剩下2块是不是就和发2块的方法一样了?
4:先发4块的情况下,剩下1块是不是就和发1块的方法一样了?
5:5块一次性发完,唯一方法
即符合 f(n) = f(n-1) + f(n-2) + … + f(1) + 1=2f(n-1)

class Solution:
    def CalulateMethodCount(self , num_money ):
        # write code here
        recur_add=0
        f=[0 for _ in range(num_money+1)]
        f[0]=1
        f[1]=1   
        recur_add=f[0]+f[1]
        for i in range(2,num_money+1):
            f[i]=recur_add
            recur_add+=f[i]
        return f[num_money]

2.撤销与恢复

撤销/恢复操作具有广泛的用途,比如word文档中输入一个单词,可以点撤销,然后可以再恢复。
编程实现如下功能: 从标准输入读取到一个字符串,字符串可包含0个或多个单词,单词以空格或者tab分隔; 如果遇到 “undo” 字符串,表示"撤销"操作,前一个字符串被撤销掉; 如果遇到"redo"字符串,表示恢复刚才撤销掉的字符串.
例如: 输入字符串 “hello undo redo world.”, 对字符串中的 undo 和 redo 处理后, 最终输出的结果为 “hello world.”

先初始化两个栈stack和redo,然后利用双栈求解。遍历词表:
遇到普通词就压入stack,并清空redo栈,因为此时写入了一个新词,再往前的词已经找不回来了;
遇到undo就从stack中弹栈至redo;
遇到redo就从redo中弹栈至stack。
最终stack中的词就是最后保留下来的词

commands = input().strip().split(" ")
stack, redo = [], []
for cmd in commands:
    if cmd == "undo":
        if stack:
            redo.append(stack.pop())
    elif cmd == "redo":
        if redo:
            stack.append(redo.pop())
    else:
        redo.clear()
        stack.append(cmd)
print(" ".join(stack))

3.密码生成

在这里插入图片描述

所谓取模运算,就是计算两个数相除之后的余数,符号是%。如a % b就是计算a除以b的余数。
直观想法
N,M=map(int,input().split())
s=[0 for _ in range(N)]
for i in range(M):
    L,R=map(int,input().split())
    s[L:R+1]=[i+1]*(R+1-L)
res=0
for i in range(N):
    res+=i*s[i]
print(res%100000009)

在这里插入图片描述

差分算法

用差分的思想。
创建数组存操作记录,在区间左端记录+i,区间右端记录-i。
创建一个优先队列,从左往右遍历所有操作,遇到+就add(i),遇到-就remove(i)。
每个位置的密码就是这时优先队列大顶端的数。
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
const int mod = 100000009;
struct node {
    int l, r, v;
};
bool operator <(node a, node b){
    return a.v < b.v;
}
int main(){
    int n, m;
    while (cin >> n >> m) {
        vector<int> v(n);
        vector<node> tmp;
        for (int i = 1; i <= m; i++) {
            int a, b;
            cin >> a >> b;
            node now; now.l = a; now.r = b; now.v = i;
            tmp.push_back(now);
        }
        sort(tmp.begin(), tmp.end(), [&](node &a, node &b) {
            return a.l < b.l;
        });
        long long ans = 0;
        priority_queue<node> q;
        int pos = 0;
        for (int i = 0; i < n; i++) {
            while(i >= tmp[pos].l && pos < m) {
                node now = tmp[pos];
                q.push(now);  #使用q来存储每个区间叠加的数
                pos++;
            }
            while (!q.empty()) {
                node now = q.top(); #优先队列大顶堆,取出最大的数
                if (now.r < i) {
                    q.pop();
                }
                else {
                    v[i] = now.v;
                    break;
                }
            }
        }
        for(int i = 0 ;i < n; i++)
        {
            ans += i * v[i];
            ans %=  mod;
        }
        cout << ans << endl;
    }
}

4. 最大体积值

一个长方体,长宽高都是质数,已知长宽高之和为n【n为[6,10000]范围内的自然数。】,求这个长方体的体积最大值。
输入值:长宽高之和。
输出值:体积的最大可能值。

示例:
输入:6 输出:8 说明:当长宽高都为2时体积最大,为8

简单说明

此题可分为两个部分:1. 质数数组生成 2. 三数之和为n
最后从符合三数之和为n的组合中找到体积最大的那组

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 得到体积的最大可能值
# @param n long长整型 长方形的长宽高之和。长宽高都为质数。
# @return long长整型
#
class Solution:
    def getMaxVolume(self , n ):
        # write code here
                ##质数数组
        odd=[]
        odd.append(1)
        odd.append(2)
        for i in range(2,n):
            if list(set([i%j!=0 for j in range(2,i)]))==[True]:
                odd.append(i)
##找到长宽高和符合要求的
        possible=[]
        for i in range(len(odd)):
            left,right=i,len(odd)-1
            while left<=right:
                if odd[i]+odd[left]+odd[right]<n:
                    left+=1
                elif odd[i]+odd[left]+odd[right]>n:
                    right-=1
                else:
                    possible.append([odd[i],odd[left],odd[right]])
                    left+=1
                    right-=1
                     
 
        max_res=0
        print(possible)
        for i in range(len(possible)):
            tmp=possible[i][0]*possible[i][1]*possible[i][2]
            if tmp>max_res:
                max_res=tmp
                  
        return max_res

5. 深信服机架

深信服的设备通常是叠放在机架上的。设备(水平放置)有1U,2U两种高度,2U的高度是1U的两倍。对于一个高度为h的机架,可以叠放多台设备,只要这些设备总高度不超过h就可以。1U、2U两种型号的设备和机架的宽度相等,而且为了避免损坏,必须水平放置设备,而不允许将设备竖直放置。

客户买了一批深信服设备,其中1U设备有a台,2U设备有b台。现在他想知道,需要多个高度为h的机架,才能全部放下这批设备?

注:每个机架都可以随意叠放1U和2U的设备,只要总高度不超过h就行,对设备的叠放顺序和数量搭配没有要求。但是不同的叠放策略对于机柜数量的需求是不一样的。比如某客户有2台1U设备和2台2U设备,当使用h=3的机架时,他可以每个机架上放一台1U和一台2U设备,这样总共两个机架就够用了。但如果执意要把两台1U设备叠放在一起,则至少需要3个机架才够用。这里我们假设客户总是按照最好的策略来叠放这些设备。
在这里插入图片描述

T=int(input()) #input的返回都是string类型
S=[[0]*3 for _ in range(T)]
for i in range(T):
    S[i][0],S[i][1],S[i][2]=map(int,input().split())
 
#input函数输入的都是string,需要先转换成int
 
#s[i][0]:a s[i][1]:b s[i][2]:h
import math
#对于每个客户
for s in S:
    res=0
#    if s[2]%2==0:#先装2,再装1
#        res+=(math.ceil(s[1]/(s[2]//2))+math.ceil(s[0]/s[2]))
#    else:
    res+=math.ceil(s[1]/(s[2]//2))
        #print(res)
    if (s[2]*res-2*s[1])>=s[0]:
            #print("T")
        res+=0
    else:
        res+=math.ceil((s[0]-(s[2]*res-2*s[1]))/s[2])
    print(res)

6. 深信服下午茶

深信服经常给员工发放下午茶,为保证新鲜,下午茶需要当天采购。

下午茶有水果和面点两种类型,其中水果和面点都有单独的采购价格,它们的价格都是整数元。

某次,负责采购的阿姨忘记了水果和面点各自的价格,但她保存了两天的采购的记录:第一天采购了a1份水果,b1份面点,总花费v1元。第二天采购了a2份水果,b2份面点,总花费v2元。

阿姨希望你帮她计算,水果和面点的实际价格分别是多少。

输入描述:

第一行一个正整数T(T<=100),表示有T组测试数据。

接下来T行,每行6个整数,a1,b1,v1, a2,b2,v2。(所有数字都>=0且 <=1000,000,000。它们的意义如题所述)

有50%的数据案例,上述六个数都属于区间[1,100];而100%的数据案例,上述六个数都属于区间[0,1e9]。

输出描述:

输出T行。

若对应的测试数据存在唯一的解,并且解正整数解,则输出两个整数,表示水果和面点的价格。

若存在多解,或者水果和面点的价格可能不是正整数,则输出UNKNOWN 。

(注:只要水果和面点的价格有可能不是正整数,就应输出UNKNOWN

T=int(input())
S=[[0]*6 for _ in range(T)]
for i in range(T):
    S[i][0],S[i][1],S[i][2],S[i][3],S[i][4],S[i][5]=map(int,input().split())
     
for s in S:
    if s[0]*s[4]-s[3]*s[1]==0 or s[3]*s[1]-s[0]*s[4]==0:
        print("UNKNOWN")
        continue
    if (s[4]*s[2]-s[5]*s[1])%(s[0]*s[4]-s[3]*s[1])!=0 or (s[3]*s[2]-s[0]*s[5])%(s[3]*s[1]-s[0]*s[4])!=0:
        print("UNKNOWN")
        continue
        #若不存在唯一解,也unknown
    #if s[0]==0
    #if s[3]/s[0]==s[4]/s[1] and s[3]/s[1]==s[5]/s[2]:
       # print("UNKNOWN")
        #continue
    if (s[4]*s[2]-s[5]*s[1])/(s[0]*s[4]-s[3]*s[1])<=0 or (s[3]*s[2]-s[0]*s[5])/(s[3]*s[1]-s[0]*s[4])<=0:
        print("UNKNOWN")
        continue
    print((s[4]*s[2]-s[5]*s[1])//(s[0]*s[4]-s[3]*s[1]),(s[3]*s[2]-s[0]*s[5])//(s[3]*s[1]-s[0]*s[4]))

7.找零

假设有硬币种类coins=[1,2,5,10],硬币不限量,现给出需要找零的钱数N,请求出找零的方案数

动态规划法解答

  1. dp[j]:代表找零钱数为 j 时的方案数
  2. 初始化dp[0]=1 代表找零钱数为0的方案数为1种,就是啥也不给
  3. 递推公式dp[j]+=dp[j-coins[i-1]] 代表前i个面值不同的硬币找出零钱j的方案数
    比如当 i 等于1,此时循环为
	  for j in range(1,N+1):
	  	dp[j]+=dp[j-1]
指的是只用1元硬币时总的找零方案数,可以推导出此时方案数(dp[0]到dp[N])都始终为1

当i=2 ,此时循环为
	  for j in range(2,N+1):
	  	dp[j]+=dp[j-2]
物理意义是,如果在只用1元硬币的基础上,又允许了2元硬币的使用,此时各找零钱数的方案数。比如找零总2元,只用1元硬币时,只能用两个1元硬币,dp[2]=1;现在允许使用2元硬币了,又多了一种直接使用2元硬币的方案dp[2]+=dp[2-2];
如果找零总4元,只用1元硬币时dp[4]=1,现在允许使用2元硬币了,dp[4]+=dp[4-2]
也即dp[4]=1+dp[4-2] ,1代表只用4个1元硬币,dp[4-2]代表规定要用一张2元硬币,剩下的往前推到种类数,这里刚推导过剩下dp[2]=2
class Solution(object):
    def giveChange(self,N):
    	coins=[1,2,5,10]
    	dp=[0 for _ in range(N+1)]
    	dp[0]=1
    	for i in range(1,len(coins)+1):
    	  for j in range(coins[i-1],N+1):
    	  	dp[j]+=dp[j-coins[i-1]]
    	  	
    	return dp[N]

8.单词搜索

在这里插入图片描述

参考

【1】牛客网
【2】

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值