开始刷第二题,预计每天3-4题
### Day5:1.201903-2 2.201909-2 3.201912-2
#### 1.201903-2:二十四点(模拟,今天重点题,栈)
(1)题目理解没有问题,但是我自己写的模拟比较复杂(100),**记得-'0'** 下次知道自己只能写复杂的模拟过程且能写出来可以不写,直接学习别人思路
(2)优化学习思路:[CCF-CSP 201903-2二十四点 三种方法 满分题解 结尾附惊天方法_ccf csp真题24点-优快云博客](https://blog.youkuaiyun.com/m0_53641110/article/details/120875227?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522172459329916800186598037%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=172459329916800186598037&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~hot_rank-3-120875227-null-null.142^v100^pc_search_result_base3&utm_term=201903-2%3A%E4%BA%8C%E5%8D%81%E5%9B%9B%E7%82%B9&spm=1018.2226.3001.4187)
(一)**使用栈来模拟四则运算过程(重点学习)**
1.利用栈”先进先出”的特性,设置一个数字栈,将数字保存在栈里。
2.利用一些基本的数学知识进行转化:将减法转换成加法(**很巧妙,可以不用写符号栈了**)。
3.直接计算乘法和除法,将所得结果压入栈中(**栈的用处的直接体现**)。
4.细节:在x和/后接的一个数字可以直接用(运算优先性),但是符号前面的一个数字需要通过栈来给出。
代码:
```
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
while(n--){
string s;
cin>>s;
stack<int> st;
for(int i=0;i<7;){
if(s[i]>='0' && s[i]<='9'){
st.push(s[i]-'0');
i++;
}
else if(s[i]=='+'){
i++;
}
else if(s[i]=='-'){
st.push( (s[i+1]-'0')*(-1) );
i+=2;
}
else if(s[i]=='x'){
int t=st.top();
st.pop();
t*=(s[i+1]-'0');
st.push(t);
i+=2;
}
else{
int t=st.top();
st.pop();
t/=(s[i+1]-'0');
st.push(t);
i+=2;
}
}
int sum=0;
while(!st.empty()){
sum+=st.top();
st.pop();
}
if(sum==24){
cout<<"Yes"<<endl;
}
else{
cout<<"No"<<endl;
}
}
return 0;
}
```
(二)分成整型数组和字符数组来模拟,不过可以先计算乘除,再计算加减
```
int a[4], i, j;
char op[3];
//从输入取出数和运算符
for(i = 0; i < 4; i++)
a[i] = s[i * 2] - '0';
for(i = 0; i < 3; i++)
op[i] = s[i * 2 + 1];
int k = 3; /* 总共有三个运算符即计算3次 */
// 先计算乘和除
for(i = 0; i < k; i++)
if(op[i] == 'x' || op[i] == '/') {
if(op[i] == 'x') a[i] = a[i] * a[i + 1];
else a[i] = a[i] / a[i + 1];
for(j = i + 1; j < k; j++) {
//后面覆盖前面
op[j - 1] = op[j];
a[j] = a[j + 1];
}
k--, i--;
}
//再计算加和减
int ans = a[0];
for(i = 0; i < k; i++)
if(op[i] == '+') {
//ans覆盖后面
ans = a[i] + a[i + 1];
a[i + 1] = ans;
} else {
ans = a[i] - a[i + 1];
a[i + 1] = ans;
}
return ans == 24;
```
#### 2.201909-2:小明种苹果(续)(模拟)
(1)题目好理解
(2)代码(100):
```
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
int T=0,D=0,E=0;
vector<bool> v(n,false);//判断E
for(int i=0;i<n;i++){
int m;
cin>>m;
int sum=0;
bool isDrop=false;
for(int j=0;j<m;j++){
int x;
cin>>x;
if(j==0){
sum=x;
}
else if(x<=0){
sum+=x;
}
else if(x>0){
if(sum>x){
isDrop=true;
}
sum=x;
}
}
T+=sum;
if(isDrop){
D++;
v[i]=true;
}
}
for(int i=0;i<n-2;i++){
if(v[i] && v[i+1] && v[i+2]){
E++;
}
}
if(v[n-2] && v[n-1] && v[0]){
E++;
}
if(v[n-1] && v[0] && v[1]){
E++;
}
cout<<T<<" "<<D<<" "<<E;
return 0;
}
```
(3)优化(最后判断E可以不用单独判断最后两个,但是不要用i%n这种判断,会超时):
```
vector<bool> v(n+2,false);//判断E
v[n]=v[0];
v[n+1]=v[1];
for(int i=0;i<n+2;i++){
if(v[i] && v[i+1] && v[i+2]){
E++;
}
}
```
#### 3.201912-2:回收站选址(小模拟)
(1)题目理解:题目只有判断一处坐标存不存在垃圾即可,即快速判断一个元素存在不存在(哈希),故而想到用set(或者用map)实现(但对于此题set更好一点,因为次数不是跟每一个元素关联的,不需要使用map键值对,只需要set判断是否存在即可)
(2)代码(100):
```
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
set<pair<int,int>> s;
vector<int> res(5,0);
for(int i=0;i<n;i++){
int x,y;
cin>>x>>y;
s.insert({x,y});
}
for(auto it=s.begin();it!=s.end();it++){
int x=it->first;
int y=it->second;
int cnt=0;
if(s.find({x,y+1})!=s.end()
&& s.find({x,y-1})!=s.end()
&& s.find({x+1,y})!=s.end()
&& s.find({x-1,y})!=s.end()
){
//可改进,见下面
if(s.find({x+1,y+1})!=s.end()){
cnt++;
}
if(s.find({x+1,y-1})!=s.end()){
cnt++;
}
if(s.find({x-1,y+1})!=s.end()){
cnt++;
}
if(s.find({x-1,y-1})!=s.end()){
cnt++;
}
res[cnt]++;
}
}
for(int i=0;i<5;i++){
cout<<res[i]<<endl;
}
return 0;
}
```
(3)优化改进:
1.set里面有个count()函数用来计数
```
cnt += s.count({x + 1, y + 1});
cnt += s.count({x + 1, y - 1});
cnt += s.count({x - 1, y + 1});
cnt += s.count({x - 1, y - 1});
res[cnt]++;
```