CCF-CSP认证考试准备第五天

开始刷第二题,预计每天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点-CSDN博客](https://blog.csdn.net/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

using namespace std;

int main(){
    int n;
    cin>>n;
    while(n--){
        string s;
        cin>>s;
        stack 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"<         }
        else{
            cout<<"No"<         }
    }
    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

using namespace std;

int main(){
    int n;
    cin>>n;
    int T=0,D=0,E=0;
    vector v(n,false);//判断E
    for(int i=0;i         int m;
        cin>>m;
        int sum=0;
        bool isDrop=false;
        for(int j=0;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         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<     return 0;
}
```
(3)优化(最后判断E可以不用单独判断最后两个,但是不要用i%n这种判断,会超时):
```
vector v(n+2,false);//判断E
v[n]=v[0];
v[n+1]=v[1];
for(int i=0;i     if(v[i] && v[i+1] && v[i+2]){
        E++;
    }
}
```

#### 3.201912-2:回收站选址(小模拟)
(1)题目理解:题目只有判断一处坐标存不存在垃圾即可,即快速判断一个元素存在不存在(哈希),故而想到用set(或者用map)实现(但对于此题set更好一点,因为次数不是跟每一个元素关联的,不需要使用map键值对,只需要set判断是否存在即可)
(2)代码(100):
```
#include

using namespace std;

int main(){
    int n;
    cin>>n;
    set> s;
    vector res(5,0);
    for(int i=0;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<     }
    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]++;
```
 

你可能感兴趣的:(CCF-CSP认证,c++,算法,数据结构)