目录
题目 A: 删数游戏
题目描述
小明的老师近日在课堂上对全班同学提出了如下的删数问题供大家思考:任意给定一个有若干个数码组成的自然数n,,
要求一个一个地在其中删除数字,共删除k个数,使得剩下的数码组成的数最小。
小明回家后写了一些数进行试验,随后来到你处坚持要你帮他核对他删数所得的结果是否正确,你能帮他个忙吗?
输入
输入的第1行是一个正整数T,表示下面有T行测试数据,(0<T<=20)。
接下来有T行,每行上有两个正整数n、k,但正整数n的有效位数len可达240位,k<len。
输出
对每组测试数据n、k,输出n被删除其中的k个数码后所的最小数字,你必须删除前导多余的0。
样例输入
2
178543 4
18541397 4
样例输出
13
1137
#include<iostream>
#include<vector>
//模拟栈
int main()
{
int n;
std::cin>>n;
while(n--)
{
std::string num;
int k,top = 0;
std::cin>>num>>k;
int num_len = num.size();
std::vector<char> ans(num_len);
for(int i=0,j=0;i<num_len;i++)
{
while (top>0 && num[i] < ans[top-1] && j < k)
{
top--;
j++;
}
ans[top++] = num[i];
}
int i =0;
while(ans[i] == '0' && i != num_len - k - 1)
{
i++;
}
while( i < num_len - k)
{
std::cout<<ans[i++];
}
std::cout<<"\n";
}
}
某位朋友的神奇解答
#include <iostream>
#include <vector>
int main()
{
int T, i = 0;
std::cin >> T;
while (T--)
{
std::string n;
int k, min = 0, j = 0;
std::cin >> n >> k;
int len = n.size() - k;
std::vector<char> a(len +1);
a[0] = n[0];
while (min != n.size() - 1 && k < n.size())
{
for (i = min + 1; i < k + 1; i++)
{
if (a[j] > n[i])
{
a[j] = n[i];
min = i;
}
}
j++;
min++;
a[j] = n[min];
k++;
}
bool flag = false;
for (int i = 0; i < len; i++)
{
if (a[i] != '0')
{
flag = true;
}
if (flag || i == len - 1)
{
std::cout << a[i];
}
}
std::cout << std::endl;
}
return 0;
}
题目 B: 服务顺序
题目描述
若干个顾客同时等待一项服务。顾客i需要的服务时间为ti。你的任务是安排n个顾客的服务次序使总的等待时间最小。总的等待时间是指每个顾客等待服务的时间的总和(自己不必计算服务时间)。
输入
有若干组测试数据,每组测试数据有两行,其第一行是一个整数n(0<=n<=4000),表示本次测试中顾客的个数,第二行是这n个顾客需要的服务时间为ti,前后两个顾客的t之间有一个空格。各行的行首、行末无多余空格,输入中给出的顾客是按从小到大的顺序排列的。
输出
对每组输入,输出该次测试中这些顾客最小的总等待时间。
样例输入
3
4 6 2
5
5 4 3 2 1
样例输出
8
20
#include<iostream>
#include<queue>
int main()
{
int n;
while (std::cin>>n)
{
std::priority_queue<int,std::vector<int>,std::greater<int>> pri_que;
int num =n;
while(n--)
{
int temp;
std::cin>>temp;
pri_que.push(temp);
}
int min_result = 0;
while(!pri_que.empty())
{
int min = pri_que.top();
pri_que.pop();
min_result = (num-1)*min + min_result;
num--;
}
std::cout<<min_result<<"\n";
}
}
题目 C: 特殊的背包
题目描述
有一个背包,总承重为c,放入背包的物品需整个放入,不得切开放入一部分,因为你目前没有切开这些物品的工具,而且你一旦切开他们的整体形象已经被破坏,这是不值得的。现有n个相当特殊的物品需要放入背包中,这n个物品重量越大价值越小,如金、银、铜、铁等物品。
现给定n个物品,请你尽可能地将物品装入背包,使得装入包的物品的总价值最大。
输入
有多组测试数据。每组有3行构成,第1行有两个正整数n和c,分别表示有n个物品和包的总承重量,第2行有n正整数p1、p2、...、pn,其中pi表示第i个物品的价值,(1≤i≤n),第3行有n正整数w1、w2、...、wn,其中wi表示第i个物品的重量值整。每行的整数之间有一个空格。(1 £ n £ 100,1 £c £ 1000)。
输出
对每组测试数据,一行输出装入背包中的物品的最大总价值。
样例输入
7 20
2 8 5 10 3 4 7
14 3 6 2 10 8 5
样例输出
30
//其实根据题目描述,这n个物品重量越大价值越小
//这道题直接无脑重量从小到大放就行了
#include<iostream>
#include<vector>
int main()
{
int num,capacity;
while (std::cin>>num>>capacity)
{
std::vector<int> values(num);
std::vector<int> weights(num);
for(int i=1;i<=num;i++)
{
std::cin>>values[i];
}
for(int i=1;i<=num;i++)
{
std::cin>>weights[i];
}
int max_value = 0;
std::vector<std::vector<int>> dp (num+1,std::vector<int>(capacity+1));
for(int i =0;i<=num;i++)
{
dp[0][i] = 0;
}
for(int i=1;i<=num;i++)
{
for(int j=capacity;j>=0;j--)
{
if(j>=weights[i])
{
dp[i][j] = std::max(dp[i-1][j],dp[i-1][j-weights[i]]+values[i]);
}
else
{
dp[i][j] = dp[i-1][j];
}
}
}
std::cout<<dp[num][capacity]<<"\n";
}
}