1、2019南大計算機本科開放日機試題(最小新整數)
給定一個十進制正整數n(0 < n < 1000000000),每個數位上數字均不爲0。n的位數爲m。
現在從m位中刪除k位(0<k < m),求生成的新整數最小爲多少?
例如: n = 9128456, k = 2, 則生成的新整數最小爲12456
輸入
第一行t, 表示有t組數據;
接下來t行,每一行表示一組測試數據,每組測試數據包含兩個數字n, k。
輸出
t行,每行一個數字,表示從n中刪除k位後得到的最小整數。
樣例輸入
2
9128456 2
1444 3
樣例輸出
12456
1
相對位置可以變的情況下:
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
using namespace std;
int main(void){
string str;
int k, t;
cin >> t;
vector<int> vec[t];
for(int i = 0; i < t; i++){
cin >> str >> k;
for(int j = 0; j < str.size(); j++){
vec[i].push_back(str[j]-48);
}
sort(vec[i].begin(), vec[i].end());
vec[i].erase(vec[i].end()-k, vec[i].end());
}
for(int i = 0; i < t; i++){
copy(vec[i].begin(), vec[i].end(), ostream_iterator<int>(cout, ""));
cout << endl;
}
return 0;
}
相對位置不可以改變:
/**
* 思路:最長上升子序列的變種
* 每遍歷到字符串中的字符,若存在比當前字符大的字符,則刪除之
* 直到刪除的個數已爲k 或遍歷到了 最後一個字符爲止
*
*/
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main() {
string num;
int k;
cin >> num >> k;
if(k == 0) {
cout << num;
return 0;
}
int len = num.length();
int finalLen = len - k;
if(finalLen <= 0) {
cout << "";
return 0;
}
int flag[len];
memset(flag,0,sizeof(flag));
int i = 1;
int j = 0;
// 有可能存在 12345 這種刪除字符數目不夠k 的情況
// 則將前 len - k 個 字符打印之
while(i < len && k > 0) {
int a = num[i] - '0';
for(int j = 0;j < i;j++) {
int b = num[j] - '0';
if(a < b && flag[j] == 0) {
flag[j] = 1;
k--;
if(k == 0) {
break;
}
}
}
i++;
}
for(int i = 0;i < len;i++) {
if(flag[i] == 0 && finalLen > 0) {
cout << num[i];
finalLen--;
}
}
return 0;
}
2、暨南大學-計算機機試(合併果子問題)
其實,就是一道經典的哈夫曼問題,大致解法:
#include <cstdio>
#include <queue>
using namespace std;
//代表小頂堆的優先隊列
priority_queue<long long, vector<long long>, greater<long long> > q;
int main(void){
int n; //n堆果子
long long temp, x, y, ans = 0;
scanf("%d", &n);
for(int i = 0; i < ans; i++){
scanf("%lld", &temp); //將初始重量壓入優先隊列
q.push(temp);
}
while(q.size() > 1){ //只要優先隊列中至少有兩個元素
x = q.top();
q.pop();
y = q.top();
q.pop();
q.push(x+y); //取出堆頂的兩個元素,求和後壓入優先隊列
ans += x+y; //累計求和的結果
}
printf("%lld\n", ans); //ans即爲消耗的最小體力
return 0;
}
hyy做法:容器中當前元素的下一個元素的值加上當前元素,最後減去容器中第一個元素即爲最小帶權路徑
#include<iostream>
#include<vector>
#include<functional>
#include <numeric>
#include<algorithm>
using namespace std;
int main(){
int n,x,a[1000],b[1000],sum=0;
cin>>n;
int m = n;
while(m--){
cin>>x;
a[m]=x;
}
vector<int> v(a,a+n);
sort(v.begin(),v.end());
vector<int>::iterator i=v.begin();
//vector<int>::iterator i1=v.begin();
//cout << "=====" << endl;
for(;i!=v.end()-1;i++)
*(i+1)+=*(i);
sum = accumulate(v.begin(), v.end(), 0);
//cout << "sum : " << sum << endl;
cout<<sum-*v.begin() << endl;
return 0;
}
3、求解100以內的素數
解法一:正常存儲素數表
#include <cstdio>
#include <cmath>
bool isPrime(int n){ //判斷n是否是素數
if(n <= 1)
return false;
int sqr = (int)sqrt(1.0*n);
for(int i = 2; i <= sqr; i++){
if(n % i == 0)
return false;
}
return true;
}
int prime[101], num = 0; //素數的個數
void findPrime(){ //求素數表
for(int i = 1; i < 101; i++){
if(isPrime(i) == true){
prime[num++] = i;
p[i] = true;
}
}
}
int main(void){
findPrime();
for(int i = 0; i < num; i++){
printf("%d", prime[i]);
if(i < num-1){
printf(" ");
}
}
return 0;
}
解法二:埃式篩法
#include <cstdio>
const int maxn = 101;
int prime[maxn], num = 0; //素數的個數
bool p[maxn] = {0}; //記錄當前下標代表的值是否是素數
void findPrime(){
for(int i = 2; i < maxn; i++){
if(p[i] == false){
prime[num++] = i;
//篩去i~100之間所有i的倍數
for(int j = i + i; j < maxn; j += i){
p[j] = true;
}
}
}
}
int main(void){
findPrime();
for(int i = 0; i < num; i++){
printf("%d", prime[i]);
if(i < num-1){
printf(" ");
}
}
return 0;
}