牛客编程巅峰赛S1第4场 - 黄金&钻石(解题报告)

题目链接:https://ac.nowcoder.com/acm/contest/6384

A-牛牛分蛋糕

题意 :分两种蛋糕,有n个盘子,两种蛋糕数量分别是a,b个。

  • 一个盘子只能放一种蛋糕
  • 盘子要用完
  • 求盘子上最少蛋糕的最大值。
  • n,a,b(1 ≤ a, b ≤ 10^5, 2 ≤ n ≤ a + b)

 输入:4 7 10

输出:3 

方法一:枚举第一种蛋糕放了多少盘子,并更新最大值 

class Solution {
public:
    /**
     * 处理函数,返回在所有分法中,蛋糕数量最少的盘子中分到最多的蛋糕数量
     * @param n int整型 n个盘子
     * @param a int整型 a蛋糕数量
     * @param b int整型 b蛋糕数量
     * @return int整型
     */
    int solve(int n, int a, int b) {
        // write code here
        int tmp=-1,numa,numb;
        for(int i=1;i<n;i++){ 
		//i是1蛋糕花了的盘子数,(n-i)是2蛋糕花了的盘子数 
        	numa=a/i;
        	numb=b/(n-i);
        	tmp=max(tmp,min(numa,numb));//更新最少蛋糕最大值 
		}
		return tmp; 
    }
};

 方法二:二分法

class Solution {
public:
    /**
     * 处理函数,返回在所有分法中,蛋糕数量最少的盘子中分到最多的蛋糕数量
     * @param n int整型 n个盘子
     * @param a int整型 a蛋糕数量
     * @param b int整型 b蛋糕数量
     * @return int整型
     */
    int solve(int n, int a, int b) {
        // write code here
        int tmp=1,l=1,r=a+b;
        while(l<=r){
        	int mid=l+r>>1;//mid是盘子中最少蛋糕
			if(a/mid+b/mid>=n)tmp=mid,l=mid+1;
			else r=mid-1; 
		}
		return tmp;
    }
};

B-牛牛凑数字

 题意:牛牛有n元钱,想去商店买数字,每个数字数量无限制,范围是1-9,价格保存在a数组中,牛牛想用这n元钱凑个最大的数字。输出满足条件的最大数字,如果一个都买不起,那么输出-1

 输入:2,[9,11,1,12,5,8,9,10,6] 

 输出:33

 hint:首先去找数量最多的,然后用剩下的钱从高到低位替换可以买的数字更大的数,就好了

class Solution {
public:
    /**
     * 得到牛牛能够凑到的最大的数字
     * @param n int整型 牛牛能够承受的价格
     * @param a int整型vector 1-9这九个数字的价格数组
     * @return string字符串
     */
    string solve(int n, vector<int>& a) {
        // write code here
    	string s;
    	int k=0,idx;
    	for(int i=8;i>=0;i--){
    		if(k<n/a[i]){
    			k=n/a[i];
    			idx=i+1;
			}
		}
		if(!k)return "-1";
		char ch = idx + '0';
		for(int i=0;i<k;i++)s+=ch;
		int mod = n - k * a[idx-1];
		for(int i=0;i<k;i++){
			int flag=0;
			for(int j=9;j>=1;j--){
				if(mod>=a[j-1]-a[idx-1]){
					mod-=a[j-1]-a[idx-1];
					flag=1;
					ch=j+'0';
					s[i]=ch;
					break;
				}
			}
			if(!flag)break;
		}
		return s;
    }
};

C-牛妹的野菜 

 题意:挖番薯。n个番薯洞,每个番薯洞都有一定数量的番薯。m条单项路径,无环。设计一条挖番薯的方案,使得可以挖到最多的番薯,并输出路径。

输入:[5,10,20,5,4,5],[[1,2],[1,4],[2,4],[3,4],[4,5],[4,6],[5,6]] 

输出:"3-4-5-6" 

hint:树上dp,dp[i]表示搜到第i个洞之前挖到最多的番薯,pre[i]表示i的上一节点,更新路径末端结点pos,最后从pos开始反向存路径

class Solution {
public:
    /**
     * 
     * @param potatoNum int整型vector 依次表示序号为1,2,3..的番薯洞各有多少个番薯
     * @param connectRoad int整型vector<vector<>> 每个一维数组[x,y]表示从第x号番薯洞到第y号有路
     * @return string字符串
     */
     
    string digSum(vector<int>& potatoNum, vector<vector<int> >& connectRoad) {
        // write code here
        int n=potatoNum.size();
        vector<int>pre(n+1,-1);//pre表示父节点,初始化为-1
        vector<int>dp(n+1,0);//dp表示到达i结点前挖到了多少番薯,初始化为0
        vector<int>e[n+1];
        for(auto p:connectRoad){
            int start = p[0];
            int end = p[1];
            e[start].push_back(end);
        }
        int pos=1;
        for(int i=1;i<=n;i++){
            dp[i]+=potatoNum[i-1];
            if(dp[i]>dp[pos])pos=i;//更新番薯数最大值的下标(路径的末端)
            for(auto j:e[i]){
                if(dp[i]>dp[j]){//更新在此之前番薯最大值
                    dp[j]=dp[i];
                    pre[j]=i;
                }
            }
        }
        string ans;
        ans+=to_string(pos);
        pos=pre[pos];
        while(pos!=-1){//ans倒着加
            ans='-'+ans;
            ans=to_string(pos)+ans;
            pos=pre[pos];
        }
        return ans;
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_43911947/article/details/107443990