北理工2019年计算机学科夏令营上机考试
第一题:类似LeetCode上括号匹配,输入的字符串包括三种字符,分别是"[" "]" "*",其中“*”可以替换为“[”、"]"或者就是它本身,要求括号能配对即可,如果能匹配,输出匹配后的结果,否则输出false。
输入:*[[***
输出:*[[]]*
输入:*[[]
输出:false
注意:输出格式的隐含要求是尽量不改变原有的*。
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<stack> using namespace std; int main() { char s[55]; char ans[55]; cin>>s; memcpy(ans,s,sizeof(s)); int l = strlen(s); stack<int> pq;//预处理,先把现有的[]匹配掉,这样就只剩下[或]了。 for(int i=0;i<l;i++) { if(s[i]=='[')pq.push(i); else if(s[i]==']'&&!pq.empty()) { int x = pq.top(); s[x]='0'; s[i]='0'; pq.pop(); } } stack<int> q;//之后就处理[或者]就好了 for(int i=0;i<l;i++) { if (s[i] == '[')q.push(i); if (s[i] == '*') { if (q.empty()) q.push(i);//星号进去的答案就不改 else { int x = q.top(); q.pop(); if (s[x] == '[')//如果是星号匹配星号两个都不改 { ans[i] = ']'; } } } if (s[i] == ']') { if (q.empty()) { cout << "false" << endl; return 0; } else { int x = q.top(); q.pop(); ans[x] = '['; } } } while (!q.empty()) { int x = q.top(); q.pop(); if(s[x]=='[') { cout<<"false"<<endl; return 0; } } cout<<ans<<endl; return 0; }
第一次做:没有考虑[*]等奇数个*的情况,解决方案是预处理,把能匹配的先匹配了(如上)。
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<stack> using namespace std; int main() { char s[50]; char ans[50];//最后的输出结果 cin >> s; memcpy(ans, s, sizeof(s)); int l = strlen(s); stack<int>q; for (int i = 0; i < l; i++) { if (s[i] == '[')q.push(i); if (s[i] == '*') { if (q.empty()) q.push(i);//星号进去的答案就不改 else { int x = q.top(); q.pop(); if (s[x] != '*')//如果是星号匹配星号两个都不改 { ans[x] = '['; ans[i] = ']'; } } } if (s[i] == ']') { if (q.empty()) { cout << "false" << endl; return 0; } else q.pop(); } } if (!q.empty()) cout << "false" << endl; else { for (int i = 0; i < l; i++)cout << ans[i]; cout << endl; } return 0; }
刘先生解题方案(很稳妥!):
#include <iostream> #include <string> #include <stack> using namespace std; struct e{//记录不匹配的括号信息和其下标; int i; char c; }; int main(){ string s; cin>>s; stack<e> sta;//结构体栈; for(int i=0;i<s.length();i++){//遍历输入的字符串,遇到 [入栈,遇到 ]判断是否可以弹出栈顶,若不能也入栈; if(s[i]=='['){ e temp; temp.i=i; temp.c='['; sta.push(temp); } if(s[i]==']'){ if(!sta.empty()){//栈不空且栈顶结构体的信息为 [才能弹出,其他情况入栈; e temp=sta.top(); if(temp.c=='[') { sta.pop(); } else{ e temp; temp.i=i;temp.c=']'; sta.push(temp); } } else{ e temp; temp.i=i;temp.c=']'; sta.push(temp); } } } if(sta.empty()) {//若遍历完后栈空,则说明本身匹配,输出,返回,程序结束; cout<<s<<endl; return 0; } else{//若不空则说明有不匹配的元素存在,一一判断是否可以修改为匹配; while(!sta.empty()){ bool change=false;//默认当前操作元素无法更改正确; e temp=sta.top();//取出栈顶一个不匹配的括号; sta.pop(); if(temp.c=='['){//若为左括号,在原字符串右边找最近的一个*改为右括号,找不到则无法改正,输出false,返回; for(int i=temp.i+1;i<s.length();i++){ if(s[i]=='*') { s[i]=']'; change=true; break; } } if(!change){ cout<<"false"<<endl; return 0; } } if(temp.c==']'){//若为 ],同理,在原字符串左侧寻找*改为左括号,找不到输出false,返回; for(int i=temp.i-1;i>=0;i--){ if(s[i]=='*') { s[i]='['; change=true; break; } } if(!change){ cout<<"false"<<endl; return 0; } } } } cout<<s;//若程序正常进行到这里说明经修改后可实现括号匹配,输出更正后字符串即可; return 0; }
第二题:输入m个数(0<m<50),从中选取不相邻的任意多个数,求最大和。
解题思路:一维动规,思路比较清晰。
每次都考虑后一位选或者不选。以6 3 7 9 -1 -1 6为例。
- 状态a[i]为第i位及之前所求的的最大和。
- 状态转移方程:a[i]=max(a[i-1],s[i]+a[i-2])
每次状态更新的时候都要看第i位的数字是否要选,那就需要去衡量s[i]+a[i-2]是否比a[i-1]更大。因为选择第i位就一定不会选择i-1位。
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; int main() { int s[55]; int a[55];//动规数组 int m; bool allneg = true; cin >> m; for (int i = 0; i < m; i++) { cin >> s[i]; if (s[i] >= 0)allneg = false; } if (m == 1) //只有一个数 { cout << s[0] << endl; return 0 ; } if (allneg)//全是负数,则输出最大的负数 { int maxneg = s[0]; for (int i = 1; i < m; i++) { maxneg = max(maxneg, s[i]); } cout << maxneg << endl; } else//至少有一个非负数,一维动规,一步步往前拱 { a[0] = max(s[0], 0); a[1] = max(s[1], a[0]); for (int i = 2; i < m; i++) { a[i] = max(a[i - 1], a[i - 2] + s[i]); } cout << a[m - 1] << endl; } system("pause"); return 0; }

浙公网安备 33010602011771号