华为8.26笔试开发岗思路分享(C++,1+1+0.9)
1. 按照题目要求实现即可
int n;
unsigned int arr[1001];
unsigned int ans[1001];
void solve() {
memset(ans, 0, sizeof(ans));
memset(arr, 0, sizeof(arr));
int n = 0;
while (cin >> arr[n++])
;
n--;
for (int i = 0; i < n; i++) {
unsigned int x = 0;
for (int j = 0; j < 32; j += 2) {
// Swap bits for each pair
x += (arr[i] & (1 << j)) << 1;
x += (arr[i] & (1 << (j + 1))) >> 1;
}
arr[i] = x;
}
unsigned int mask = 3; // 0...011
// Shift bits
for (int i = 0; i < n; i++) {
int j = (i + 1) % n;
ans[j] = (arr[i] & mask) << 30;
ans[j] += arr[j] >> 2;
}
for (int i = 0; i < n; i++) {
cout << ans[i] << " ";
}
cout << endl;
} int n;
int w[101]; // width
int h[101]; // height
int pre[101]; // prefix sum
void solve() {
char c;
string s;
cin >> s;
int b = s.find("],[");
// Divide into 2 substrings according to b.
string s1 = s.substr(1, b - 1);
string s2 = s.substr(b + 3, b - 1);
// Use stringstream to parse data
stringstream ss1(s1), ss2(s2);
int n = 0;
// read width
while (!ss1.eof()) {
ss1 >> w[n++];
if (w[n - 1] < 1 || w[n - 1] > 100) {
P1(0);
return;
}
if (ss1.eof()) break;
ss1 >> c;
}
// read height
n = 0;
while (!ss2.eof()) {
ss2 >> h[n++];
if (h[n - 1] < 1 || h[n - 1] > 100) {
P1(0);
return;
}
if (ss2.eof()) break;
ss2 >> c;
}
// reconstruct input
string cs; // correct string
cs += "[";
cs += w[0] + '0';
for (int i = 1; i < n; i++) {
cs += ',';
cs += w[i] + '0';
}
cs += "],[";
cs += h[0] + '0';
for (int i = 1; i < n; i++) {
cs += ',';
cs += h[i] + '0';
}
cs += "]";
if (cs != s) {
P1(0);
return;
}
// solve
pre[0] = 0;
for (int i = 0; i < n; i++) {
pre[i + 1] = pre[i] + w[i];
}
int ans = 0;
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
int wi = pre[j + 1] - pre[i];
int he = INT_MAX;
for (int k = i; k <= j; k++) {
he = min(he, h[k]);
}
ans = max(wi * he, ans);
}
}
cout<<ans<<endl;
} 3. dfs加剪枝。dfs(j,c)代表第j个字符是c。w是输入单词,a数组代表w剩余未分配的正确位置正确字符,b代表w剩余未分配的错误位置正确字符。如果w[j]==c,则a[i]--,如果c在w的其他位置,则b[i]--,然后继续dfs。剪枝条件是:1. a[i]<0, 2. b[i]<0, 3. a[i]+b[i] > p-j (即后续长度不够分配这么多正确字符)。 int p, n;
string w[101]; // words
int a[101], b[101]; // a: correct position, b: incorrect position
string ans = "";
bool dfs(int j, char c) {
for (int i = 0; i < n; i++) { // prune
if (a[i] < 0 || b[i] < 0 || a[i] + b[i] > (p - j)) {
return false;
}
}
ans += c;
vector<int> st(n, 0); // if dfs fails, we need to use st to restore a and b
int cnt = 0;
for (int i = 0; i < n; i++) {
if (c == w[i][j]) { // c is at correct position
a[i]--;
st[i] = 1;
cnt += a[i];
} else if (w[i].find(c) != -1) { // c is at wrong position
b[i]--;
st[i] = 2;
cnt += b[i];
}
}
// cnt = a[i] + b[i] for all i
if (j == p - 1 && cnt == 0) return true; // end of dfs, check correctness
for (char d = 'a'; d <= 'z'; d++) { // continue dfs
if (ans.find(d) != -1) continue; // d is already used
if (dfs(j + 1, d)) return true;
}
ans.pop_back(); // dfs fails, restore a[i], b[i]
for (int i = 0; i < n; i++) {
if (st[i] == 1)
a[i]++;
else if (st[i] == 2)
b[i]++;
}
return false;
}
void solve() {
cin >> p >> n;
for (int i = 0; i < n; i++) {
cin >> w[i];
cin >> a[i];
cin >> b[i];
}
for (char c = 'a'; c <= 'z'; c++) {
if (dfs(0, c)) {
cout << ans << endl;
return;
}
}
} 举例: 5 5 cloxy 3 0 cxmnu 1 1 kcotd 2 1 apqud 2 0 bldwz 1 1开始:a = {3,1,2,2,1}, b = {0,1,1,0,1}
正确路线:
dfs(0,c): a = {2,0,2,2,1}, b = {0,1,0,0,1} (因为i=0,1,c是正确字符,i=2, w包含c但是在错误位置)
-->dfs(1,l) : a = {1,0,2,2,0}, b = {0,1,0,0,1}
---->dfs(2,o): a = {0,0,1,2,0}, b = {0,1,0,0,1}
------>dfs(3,u): a = {0,0,1,1,0}, b = {0,0,0,0,1}
-------->dfs(4,d): a = {0,0,0,0,0}, b = {0,0,0,0,0} 返回正确结果
错误路线举例:
cloxy:
dfs(0,c): a = {2,0,2,2,1}, b = {0,1,0,0,1}
-->dfs(1,l) : a = {1,0,2,2,0}, b = {0,1,0,0,1}
---->dfs(2,o): a = {0,0,1,2,0}, b = {0,1,0,0,1}
------>dfs(3,x): a = {-1,0,1,2,0}, b = {0,-1,0,0,1} 有负数,返回错误
abijk:
dfs(0,a): a = {3,1,2,1,1}, b = {0,1,1,0,1}
-->dfs(1,b): a = {3,1,2,1,1}, b = {0,1,1,0,0}
---->dfs(2,i): a = {3,1,2,1,1}, b = {0,1,1,0,0}
------>dfs(3,j}: a[0]+b[0] = 3 > p-j = 2 后续字符不够分配三个正确字母,返回错误
后续优化思路:这题只过了90%,应该是超时。考虑:因为每个字母只会出现一次,因为可以用bitmap来保存字母是否出现过,用string::find是线性时间,bitmap可以达到O(1)时间。第一次写dfs加剪枝,写的太慢没时间改了。
