题目链接:https://ac.nowcoder.com/acm/contest/6384
A-牛牛分蛋糕
题意 :分两种蛋糕,有n个盘子,两种蛋糕数量分别是a,b个。
- 一个盘子只能放一种蛋糕
- 盘子要用完
- 求盘子上最少蛋糕的最大值。
- n,a,b(1 ≤ a, b ≤ , 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;
}
};