Keep2019屆校招演算法筆試題
阿新 • • 發佈:2019-01-08
1. 輸入一個字串和整數k,每3k個子串,將子串前面的k個字元反轉,後面2*k個子串保持原樣。如果剩餘的子串長度不足3k,則如果長度小於k,此末尾子串全部反轉,如果剩餘的子串長度大於k且小於3k,則把前面的k個子串翻轉,後面的末尾字元都保持原樣。
程式碼如下:
#include<iostream> #include<string> #include<algorithm> using namespace std; int main() { string str; int k; cin >> str >> k; if (k <= 0) { cout << str << endl; return 0; } int n = str.size() / (3 * k); int t = str.size() - 3 * k*n; int i = 0, j = 0; for (; j < n; j++, i += 3 * k){ reverse(str.begin() + i, str.begin() + i + k); } if (t<k&&t>0){ reverse(str.begin() + i, str.end()); } if (t >= k) { reverse(str.begin() + i,str.begin()+i+k); } cout << str << endl; return 0; }
2.揹包問題的變形,第一行輸入容量Cap,和物體個數n,接下來n行表示n組物體體重和物體價值,求使得在此容量一定的條件下物體價值最大化的物品取法。1表示取物品,0表示不取物品。典型的動態規劃問題,就是要加一個回溯函式。程式碼如下:
#include<iostream> #include<algorithm> using namespace std; int fun(int** f, int i,int cap, int n, int* weight, int* profit) { if (f[i][cap] > 0) { return f[i][cap]; } if (i == n) { f[i][cap] = weight[n] <= cap ? profit[i] : 0; return f[i][cap]; } if (weight[i] > cap) { f[i][cap] = fun(f, i + 1, cap, n, weight, profit); } else { f[i][cap] = max(fun(f, i + 1, cap, n, weight, profit), fun(f, i + 1, cap - weight[i], n, weight, profit) + profit[i]); } return f[i][cap]; } void traceback(int** f, int* weight, int cap, int n, int* x) { for (int i = 1; i <n; i++) { if (f[i][cap] == f[i + 1][cap]) { x[i] = 0; } else { x[i] = 1; cap -= weight[i]; } } x[n]= weight[n] <= cap ? 1 : 0; } int main() { int cap, n; cin >> cap>> n; int* profit = new int[n+1]; int* weight = new int[n+1]; for (int i =1; i <=n; i++) { cin >> weight[i] >> profit[i]; } int** f = new int*[n+1]; for (int i =0; i <=n; i++) { f[i] = new int[cap+1]; for (int j = 0; j <= cap; j++) { f[i][j] = -1; } } int* x = new int[n + 1]; //fun(f,cap,n,weight,profit); fun(f,1,cap,n,weight,profit); traceback(f,weight,cap,n,x); for (int i = 1; i <= n; i++) { cout << x[i] << endl; } delete [] profit; delete [] weight; for (int i = 0; i <=n; i++) { delete[] f[i]; } delete [] f; return 0; }
方法二,可以用迭代法寫fun函式,程式碼如下
void fun(int** f, int cap, int n,int* weight,int* profit) { int ymax = min(weight[n]-1, cap); for (int y = 0; y <=ymax; y++) { f[n][y] = 0; } for (int y =weight[n]; y <= cap; y++) { f[n][y] = profit[n]; } for (int i = n-1; i>=1; i--) { ymax = min(weight[i]-1, cap); for (int y = 0; y <= ymax; y++) { f[i][y] = f[i + 1][y]; } for (int y = weight[i]; y <= cap; y++) { f[i][y] = max(f[i + 1][y], f[i + 1][y - weight[i]] + profit[i]); } } }
3.給定一個數字字串,例如“1234”,輸入一個整數k,例如4。求出所有可以被k整除的子串組合,此例輸出12,124,24,4
(假設,子串的字元相對順序是不能變化的,記不清題目了,,,,,如果是不管順序,那就複雜了,先對字串排序,然後呼叫bool next_permutation(iterator start,iterator end))產生此字串的下一排列,即對所有可能的排列進行遞迴。)
#include<iostream>
#include<string>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
void dfs(string str,int b,string s,int k,set<int>& ret,vector<int>& used)
{
if (!s.empty()&&stoi(s)%k == 0) {
ret.insert(stoi(s));
}
for (int i = b; i < str.size(); i++) {
if (used[i] == 0) {
used[i] = 1;
dfs(str, b + 1, s.append(1, str[b]), k, ret,used);
s.pop_back();
dfs(str, b + 1, s, k, ret,used);
used[i] = 0;
}
}
}
int main()
{
string str;
int k;
getline(cin, str);
cin >> k;
set<int> ret;
vector<int> used(str.size(), 0);
dfs(str,0,"",k,ret,used);
for (int a : ret) {
cout << a << endl;
}
system("pause");
return 0;
}