202212 CSP认证 | 现值计算 训练计划 JPEG 解码

现值计算
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n; double i;
    cin >> n >> i;
    double sum = 0;
    for(int k = 0;k <= n;k ++){
        int x; cin >> x;
        double y = pow((1 + i), -1 * k);
        sum += (x * y);
    }
    cout << sum;
    return 0;
}

训练计划
代码难度不高,有一个点容易错,也就是第31行;
涉及有多个课程依赖课程k的情况,此时k的最晚开始时间,是这几个中最早的。
例如有两门课的最晚开始时间是8,9;则A的最晚开始时间是8号而不是9号(也就是取决于最早的一个);八号前必须完成A,不然会导致所有任务无法完成

#include<bits/stdc++.h>
using namespace std;
const int M = 110;
int pre[M], early[M], latest[M], need[M];
int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);

    int n, m; cin >> n >> m;
    for(int i = 1;i <= m;i ++) cin >> pre[i];
    for(int i = 1;i <= m;i ++) cin >> need[i];
    bool flag = true;  //能否完成
    //先计算最早开始时间
    for(int i = 1;i <= m;i ++){
        if(pre[i]) early[i] = early[pre[i]] + need[pre[i]];  //只有一个前驱节点且前驱节点的编号必定小于当前节点
        else early[i] = 1;
        if(early[i] + need[i] - 1 > n) flag = false;  //超时
    }
    for(int i = 1;i <= m;i ++) cout << early[i] << ' ';
    cout << endl;

    if(flag){   //可以完成, 推算最晚时间
        for(int i = m;i >= 1;i --){     //反着算
            if(latest[i]) continue;    //已经完成计算了
            latest[i] = n + 1 - need[i];
            int j = i;
            while(pre[j]){     //找前驱节点
                int t = latest[j];
                j = pre[j];
                if(latest[j] == 0)  latest[j] = t - need[j];
                else latest[j] = min(latest[j], t - need[j]);
            }
        }
        for(int i = 1;i <= m;i ++) cout << latest[i] << ' ';
    }
    
    return 0;
}

JPEG 解码
一道特别幸福简单的第三题…都不敢想象在考场上碰见这种题目会有多幸福。直接按照题目意思做就好了,感觉比第二题还简单…而且数组特别小完全没有超时压力
在这里插入图片描述

补充一个对小数处理的部分,包括本题涉及的四舍五入取整以及输出取整:C++ 实现四舍五入的几种方法

直接上满分代码

#include<bits/stdc++.h>
using namespace std;
const int N = 10;
const double pi = acos(-1);
int Q[N][N], M[N][N];
double M1[N][N];
vector<int> Data;

//填充函数
void filling()
{
    int dir = 1;  //1是右上 0是左下
    int i = 0, j = 0;
    for(int k = 0;k < Data.size(); k ++){
        M[i][j] = Data[k];
        if(dir == 1){   //如果当前方向是右上方
            if(j == 7) {i ++; dir = 0;}  //触碰到右边界
            else if(i == 0) {j ++; dir = 0;}  //触碰到上边界
            else {i --; j ++; }
        }else{    //向左下方运动
            if(i == 7) {j ++; dir = 1;}  //触碰到下边界
            else if(j == 0) {i ++; dir = 1;} //触碰到左边界
            else {i ++; j --;}
        }
    }
}
//逐项相乘
void multiply()
{
    for(int i = 0;i < 8;i ++){
        for(int j = 0;j < 8;j ++){
            M[i][j] *= Q[i][j];
        }
    }
}
double alpha(int x)
{
    return x == 0 ? sqrt(0.5) : 1;
}
void change()
{
    for(int i = 0;i < 8;i ++){
        for(int j = 0;j < 8;j ++){
            double x = 0;
            double mul1 = (pi / 8) * (i + 0.5);  //对于每个i,j mul1和mul2是确定的,在循环外就算了
            double mul2 = (pi / 8) * (j + 0.5);
            for(int u = 0;u < 8;u ++){
                for(int v = 0;v < 8;v ++){
                    x += alpha(u)*alpha(v)*M[u][v]*cos(mul1*u)*cos(mul2*v);
                }
            }
            x /= double(4);
            x = round(x + 128);
            x = x > 255 ? 255 : x;
            x = x < 0 ? 0 : x;
            M1[i][j] = x;
        }
    }
}
int main()
{
    int n, T;
    ios::sync_with_stdio(false);
    cin.tie(0);
    for(int i = 0;i < 8;i ++)
        for(int j = 0;j < 8;j ++)
            cin >> Q[i][j];
    cin >> n >> T;

    for(int i = 0;i < n; i ++){
        int x; cin >> x;
        Data.push_back(x);
    }

    if(T == 0) {
        filling();
        for(int i = 0;i < 8;i ++){
            for(int j = 0;j < 8;j ++){
                cout << M[i][j] << ' ';
            }
            cout << "\n";
        }
    }
    else if(T == 1){
        filling();
        multiply();
        for(int i = 0;i < 8;i ++){
            for(int j = 0;j < 8;j ++){
                cout << M[i][j] << ' ';
            }
            cout << "\n";
        }
    }
    else {
        filling();
        multiply();
        change();
        for(int i = 0;i < 8;i ++){
            for(int j = 0;j < 8;j ++){
                cout << M1[i][j] << ' ';
            }
            cout << "\n";
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值