中国矿业大学2021学年算法设计与分析实验课OJ2

1.Contest2425 - 毕老师算法实验一

传送门在这里
题目总览:

中国矿业大学2021学年算法设计与分析实验课OJ2_第1张图片

A.排列问题

// 排列问题
// 输入一个可能含有重复字符的字符串,打印出该字符串中所有字符的全排列。
#include
using namespace std;
bool IsSwap(vector &chars, int nBegin, int nEnd)
{
    for(int i=nBegin; i &chars, int k, int m)
{
    if(k==m) 
    {
        for(const char x:chars) 
        {
            cout< &chars)
{
    Perm(chars, 0, chars.size()-1);
}
// 字符串
bool IsSwap(string str, int nBegin, int nEnd)
{
    for(int i=nBegin; i chars;
    // int n;
    // cin>>n;
    // char ele;
    // for(int i=0; i>ele;
    //     chars.push_back(ele);
    // }
    // // for(const char x:chars) cout<>str;
    Foo2(str);
    system("pause");
    return 0;
}

B.快速幂

// B.快速幂
#include
using namespace std;
const long long Mod = 1e8 + 7;
typedef long long ll;
ll Pow(ll base, ll power)
{
    ll result = 1;
    for(int i=1; i<=power; ++i)
    {
        result *= power;
        result %= 1000;  //每步结果提前进行取模
    }
    return result%1000;
}
// 快速幂
// 所以我们快速幂算法的核心思想就是每一步都把指数分成两半,
// 而相应的底数做平方运算。这样不仅能把非常大的指数给不断变小,
// 所需要执行的循环次数也变小,而最后表示的结果却一直不会变
ll fastPow(ll base, ll power)
{
    ll result = 1;
    while(power>0)
    {
        if(power%2 == 0)
        {
            base = base*base % Mod;
            power /= 2;
        }
        else 
        {
            power -= 1;
            result = result*base % Mod;
            base = base*base % Mod;
            power /= 2;
        }
    }
    return result;
}
ll myPow(int x)
{
    ll result = 0;
    for(int i=1; i<=x; ++i)
        result += fastPow(i, i);
    return (result+1)%Mod;
}
int main()
{
    int x;
    while(cin>>x)
    {
        cout<

C.求第k小的数

// C.求第k小的数
#include
using namespace std;
int Partition(int a[], int low, int high);
template
int RandomizedPartition(Type a[], int p, int r);
template
void RandomizedQuickSort(Type a[], int p, int r);
template
Type RandomizedSelect(Type a[], int p, int r, int k);
int main()
{
    // int n, k;
    // cin>>n>>k;
    // vector vec;
    // for(int i=0; ikey) --high;
        a[low] = a[high];
        while(low
int RandomizedPartition(Type a[], int p, int r)
{
    int i = rand()%(r-p+1) + p;
    swap(a[i], a[p]);
    return Partition(a, p, r);
}
// template
// void RandomizedQuicksort(Type a[], int p, int r)  //随机快排
// {
//     if(p
Type RandomizedSelect(Type a[], int p, int r, int k)  //随机划分,选择
{
    if(p == r) return a[p];
    int loc = RandomizedPartition(a, p ,r);
    int count = loc-p+1; //count为a[p:r]中的元素个数
    if(k<=count) return RandomizedSelect(a, p, loc, k);
    else return RandomizedSelect(a, loc+1, r, k-count);
}

D.内部收益率

// D.内部收益率
#include
using namespace std;
int main()
{
    int a[100], n;
    while(scanf("%d", &n) && n)
    {
        for(int i=0; i<=n; i++) scanf("%d", a+i);
        double x = -1.0, y=1e6, irr, npv;
        for(int j=0; j<200; j++)
        {
            irr = (x+y)/2;   //枚举irr的取值范围[-1.0, 1e6], 二分法逼近 (至于这个范围怎么来的,我就不清楚了.数学问题)
            npv = 0;
            for(int k=0; k<=n; k++)
                npv += 1.0*a[k]/pow(1+irr, k);
            if(fabs(npv)<1e-6) break;  //小于一个阈值,认为就是方程的解
            if(npv < 0) y = irr;
            if(npv > 0) x = irr;
        }
        printf("%.2lf\n", irr);
        memset(a, 0, sizeof(a));  //每次重置a数组
    }
    // cout<<9/2.25<

E.跳台阶

// 跳台阶
#include
using namespace std;
// f(x) = f(x-1) + f(x-2)
int climbStairsMemo(int n, vector& memo)
{
    if(memo[n]>0) return memo[n];  //记录数组
    if(n==1 || n==2) memo[n] = n;
    else memo[n] = climbStairsMemo(n-1, memo) + climbStairsMemo(n-2, memo);
    return memo[n];
}
int climbStairs(int n) {
    vector memo(n+1, 0);
    return climbStairsMemo(n, memo);
}

// 滚动数组 将空间复杂度由O(n)优化成O(1)
int climbStairs2(int n)
{
    int p=0, q=0, r=1;
    for(int i=1; i<=n; i++)
    {
        p = q;
        q = r;
        r = p+q;
    }
    return r;
}

int main()
{
    int n;
    cin>>n;
    cout<

2.Contest2445 - 毕老师算法实验二

传送门在这里
题目总览:
中国矿业大学2021学年算法设计与分析实验课OJ2_第2张图片

A.沙子的质量

// A.沙子的质量  OJ作业一D题
// 动态规划
#include
using namespace std;
const int inf = 0x3f3f3f3f;  //为什么用0x3f3f3f3f而不用0xffffff  https://blog.csdn.net/jiange_zh/article/details/50198097
int Compute(int *nums, int n)
{
    int Sum[n+1]={0};
    int DP[n+1][n+1];   //之前用DP[1005][1005],导致栈空间溢出  https://blog.csdn.net/kangyupl/article/details/90723367
    memset(DP, inf, sizeof(DP));
    for(int i=1; i<=n; i++)
    {
        Sum[i] = Sum[i-1] + nums[i];
        DP[i][i] = 0;
    }
    for(int Len=2; Len<=n; Len++)
        for(int left=1; left<=n-Len+1; left++)
        {
            int right = left+Len-1;
            for(int k=left; k>n;
    int nums[n+1];
    nums[0] = 0;
    for(int i=1; i<=n; ++i) cin>>nums[i]; 
    cout<

B.最长公共子序列

// B.最长公共子序列 OJ作业一F题
// 动态规划
#include
using namespace std;
int longestCommonSequence(string a, string b)
{
    int M = a.size();
    int N = b.size();
    vector> DP(M+1, vector(N+1, 0));
    for(int i=1; i<=M; ++i)
    {
        for(int j=1; j<=N; ++j)
        {
            if(a[i-1]==b[j-1]) DP[i][j] = DP[i-1][j-1] + 1;
            else DP[i][j] = max(DP[i-1][j], DP[i][j-1]);
        }
    }
    return DP[M][N];
}
int main()
{
    string a, b;
    cin>>a>>b;
    cout<

C.三角形的路径权

// C.三角形最小路径权
// Leetcode 125题
// 动态规划

#include
using namespace std;
// 理解错误,直角三角形的情况.
int minimumTotal2(vector> &triangle)
{
    int n = triangle.size();
    vector> dp(n, vector(n));
    dp[0][0] = triangle[0][0];
    dp[1][0] = triangle[1][0], dp[1][1] = triangle[0][0]+triangle[1][1];
    if(n==2) return dp[1][1];
    for(int i=2; i> &triangle)
{
    int n = triangle.size();
    vector> dp(n, vector(n,0));
    dp[0][0] = triangle[0][0];
    for(int i=1; i>n;
    vector> triangle(n, vector(n));
    for(int i=0; i>triangle[i][j];
    }
    cout<

D.跳跃游戏Ⅱ

// D.跳跃游戏Ⅱ 
// LeetCode第45题
// 贪心算法
#include
using namespace std;
// 思想就一句话:每次在上次能跳到的范围(end)内选择一个能跳的最远的位置(也就是能跳到max_far位置的点)作为下次的起跳点 !
int Jump(vector &nums)
{
    int n = nums.size();
    int max_far = 0;  //目前能够跳到的最远位置
    int step = 0;
    int end = 0;  //上次跳跃可到达的范围右边界
    for(int i=0; i>n; 
    vector nums(n);
    for(int i=0; i>nums[i];
    cout<

E.字母排序

// E.字母排序
// 最长不降子序列
#include
using namespace std;
// 1.LIS ---> LCS  最长递增子序列(排序+LCS)
// const int N = 1010;
// int DP[N][N];
// int DIR[N][N];
// int LCS_Length(string a, string b)
// {
//     int m = a.size();
//     int n = b.size();
//     for(int i=1; i<=m; i++)
//     {
//         for(int j=1; j<=n; j++)
//         {
//             if(a[i-1] == b[j-1])
//             {
//                 DP[i][j] = DP[i-1][j-1] + 1;
//                 DIR[i][j] = 1;
//             }
//             else if(DP[i-1][j] > DP[i][j-1])
//             {
//                 DP[i][j] = DP[i-1][j];
//                 DIR[i][j] = 2;
//             }
//             else 
//             {
//                 DP[i][j] = DP[i][j-1];
//                 DIR[i][j] = 3;
//             }
//         }
//     }
//     return DP[m][n];
// }
// void LCS(string a, int i, int j)
// {
//     if(i==0 || j==0) return;
//     if(DIR[i][j] == 1)
//     {
//         LCS(a, i-1, j-1);
//         cout<>a;
//     cin.ignore();   //空格
//     getline(cin, str);
//     str += ' ';
//     string b;
//     int Start_pos = 0;
//     int add = 0;
//     for(int i=0; i>test;
//     // int add = 0;
//     // cout< &nums)
// {
//     int n = nums.size();
//     if(n==0) return 0;
//     vector dp(n, 1);
//     for(int i=0; i nums[j])
//             {
//                 dp[i] = max(dp[j]+1, dp[i]);
//             }
//         }
//     }
//     return *max_element(dp.begin(), dp.end());
// }
// int main()
// {
//     int n;
//     while(scanf("%d", &n) && n)
//     {
//         vector nums(n);
//         for(int i=0; i &nums, int l, int r, int target)   //在nums数组中找到第一个大于target的数,然后更新它
{
    if(l == r) return l;
    int mid;
    while(l <= r)
    {
        mid = (l+r)/2;
        if(nums[mid] == target) return mid;  //return mid!
        else if(nums[mid] > target) r = mid-1;
        else l = mid+1;
    }
    return l;
}
int LengthOfLIS(vector &nums)
{
    int n = nums.size();
    vector B(n+1);
    B[0] = 0;
    B[1] = nums[0];
    int len = 1; //表示B数组的长度
    for(int i=1; i B[len])
        {
            B[++len] = nums[i]; 
        }
        else if(nums[i] < B[len])
        {
            int pos = BinarySearch(B, 1, len, nums[i]);  //在B数组中找到第一个大于nums[i]的元素位置
            cout< d[len] 则更新 len = len + 1
// 否则在 d[1...len] 中 找到 d[i-1] < nums[j] <  d[i]的pos值,然后更新d[i] = nums[j]
int lengthOfLIS(vector &nums)
{
    int len = 1, n = int(nums.size());
    if(n == 0) return 0;
    vector d(n+1, 0);
    d[len] = nums[0];
    for(int i=1; i d[len])
            d[++len] = nums[i];
        else
        {
            int l = 1, r = len, pos = 0;        //如果找不到说明所有的数都比nums[i]大,此时要更新d[1]
            while(l <= r)
            {
                int mid = (l+r) >> 1;
                if(d[mid] < nums[i])
                {
                    pos = mid;
                    l = mid+1;
                }
                else r = mid-1;
            }
            d[pos+1] = nums[i];
        }
    }
    return len;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        vector nums(n);
        for(int i=0; i>nums[i];
        cout<

3.Contest2453 - 毕老师算法实验三

传送门在这里
题目总览:
中国矿业大学2021学年算法设计与分析实验课OJ2_第3张图片

A.Homework

// D.Homework
// 正确!
#include
using namespace std;
bool cmp(pair a, pair b)
{
    return a.second/a.first > b.second/b.first;
}
int main()
{
    int M, N;
    while(scanf("%d%d", &M, &N) && (M && N))
    {
        vector> vec;
        double time, value;
        for(int i=0; i(time, value));
        }   
        sort(vec.begin(), vec.end(), cmp);
        double TimeTotal = N;
        double ValueTotal = 0;   //double类型,如果写为int类型答案错误
        for(const auto x:vec) cout<<"("< x:vec)
        {
            if(TimeTotal-x.first >= 0)
            {
                cout<<"Flag1"<

B.区间包含问题

// E.区间包含问题
// 贪心算法  类似于活动安排问题
#include
using namespace std;
const int maxn = 10010;
struct Node
{
    int left, right;
}node[maxn];
bool cmp(Node a, Node b)
{
    return a.right < b.right;
}
int main()
{
    int n, m;
    scanf("%d %d", &n, &m);

    for(int i=0; i=pos && node[j].right<=r)
            {
                cout<

C.最长子序列

// F.最长子序列(最大子段和)
#include
using namespace std;
// 1.递归分治法
// f(i) = max(f(i-1)+nums[i], nums[i])  考虑f(i-1)带来的是正能量还是负能量
// f(i) 代表以第 i 个数结尾的「连续子数组的最大和」,那么很显然我们要求的答案就是:
// max(0-i-1){f[i]}
int maxSubArray(vector &nums)
{
    int n = nums.size();
    if(n==0) return {};
    if(n==1) return nums[0];
    vector f(n);
    f[0] = nums[0];
    for(int i=1; i &nums)
{
    int n = nums.size();
    if(n==0) return {};
    int pre = 0, maxAns = nums[0];
    for(const int  x:nums)
    {
        pre = max(pre+x, x);  //pre记录当前x前面的连续子数组的最大和,即f[i-1],不断更新. 类似于滚动数组 
        maxAns = max(maxAns, pre);
    }
    return maxAns;
}
int main()
{
    int n;
    while(~scanf("%d", &n))
    {
        vector nums(n);
        for(int i=0; i

D.三值排序

// D.三值排序
#include
using namespace std;
int ThreeSort(vector &nums)
{
    int n = nums.size();
    int a=0, b=0, c=0;
    for(int i=0; i>n;
    vector nums(n);
    int a=0, b=0, c=0;
    for(int i=0; i

E.法师康的工人

// E.法师康的工人
// 这一题有点问题,我好像没改过来
#include
using namespace std;
bool cmp(pair a, pair b)
{
    return a.second < b.second;
}
int main()
{
    int n;
    cin>>n;
    vector> vec;
    int left, right;
    for(int i=0; i(left, right));
    }
    sort(vec.begin(), vec.end(), cmp);
    int left_border = vec[0].first;
    int right_border = vec[0].second;
    int max_ContinuousLength = right_border-left_border;
    int max_IntervalLength = 0;
    for(int i=1; i

4.Contest2462 - 毕老师算法实验四

传送门在这里
题目总览:
中国矿业大学2021学年算法设计与分析实验课OJ2_第4张图片

A.凯撒加密法

// A.ż­ČöĂÜÂë
#include
using namespace std;
string CaesarCipher(string ciphertext, int n)
{
    int length = ciphertext.size();
    for(int i=0; i>ciphertext;
    //     cin.ignore();
    //     getline(cin, ciphertext);
    //     int k;
    //     cin>>k;
    //     k = k%26;
    //     cout<>str[i];
        cin>>change[i];
        change[i] %= 26;
    }
    for(int i=0; i

B.维吉尼亚密码

// B.¸ĽźŞÄáŃÇĂÜÂë
#include
using namespace std;
string fill(string key, string plainText)
{
    int len1 = key.size();
    int len2 = plainText.size();
    if(len1 < len2) 
    {
        int num = len2 - len1;
        string temp = key;
        for(int i=0; i>key>>cipherText;
    key = fill(key, cipherText);
    // cout<

C.简单的密码

#include
using namespace std;
int main()
{
    int n;
    int f[35] = {0, 0, 0, 1};
    for(int i=4; i<=30; ++i)
        f[i] = f[i-1]*2 + pow(2, i-4) - f[i-4];
    while(cin>>n && n>=1 && n<=30)
        cout<

D.有趣的素数

// 带佬代码
#include
#include
#include
using namespace std;
int n,ans,last;
bool visited[32];
bool isPrime[40]={0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,0};
void pc(int cur)
{
    if(cur == n && isPrime[1+last])
    {
        ans++;
        return;
    }
    for(int i = 2; i <= n; i++)
    {
        if(!visited[i] && isPrime[last+i])
        {
            int t = last;
            last = i;
            visited[i] = true;
            pc(cur+1);
            visited[i] = false;
            last = t;
        }
    }
}
int main()
{
    while(~scanf("%d",&n))
    {
        memset(visited,0,sizeof(visited));
        ans = 0;
        last = 1;
        pc(1);
        printf("%d\n",ans);
    }
    return 0;
}

E.数据加密

// E.数据加密
#include
using namespace std;
string CipherCompute(string PlainText)
{
    int n = PlainText.size();
    string ans;
    if(n==0) return {};
    if(n==1) return PlainText;
    int left = 0, right = n-1;
    while(n>0)
    {
        if(PlainText[left] < PlainText[right])
        {
            ans += PlainText[left];
            left++;
            n--;
        }
        else if(PlainText[left] > PlainText[right])
        {
            ans += PlainText[right];
            right--;
            n--;
        }
        else 
        {
            int temp_left = left+1, temp_right = right-1;
            while(temp_left=0 && temp_left <= temp_right && PlainText[temp_left] == PlainText[temp_right])
            {
                temp_left++;
                temp_right--;
            } 
            if(PlainText[temp_left]>PlainText[temp_right])
            {
                ans += PlainText[right];
                right--;
                n--;
            }
            else
            {
                ans += PlainText[left];
                left++;
                n--;
            } 
        }
    }
    return ans;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        string PlainText;
        cin>>PlainText;
        string Cipher = CipherCompute(PlainText);
        cout<
#include
#include
using namespace std;
int main()
{
    int n;
    char str[2005],ans[2005];
    while(~scanf("%d",&n))
    {
        scanf("%s",str);
        int i = 0,j = n-1;
        while(i <= j)
        {
            bool flag = false;
            for(int k = 0; i+k < j-k; k++)
            { 
                if(str[i+k] < str[j-k])
                {
                    flag = true;
                    break;
                }
                if(str[i+k] > str[j-k]) break;
            }
            if(flag) printf("%c",str[i++]);
            else printf("%c",str[j--]);
        }
        printf("\n");
    }
    return 0;
}

中国矿业大学2021学年算法设计与分析实验课OJ2_第5张图片
中国矿业大学2021学年算法设计与分析实验课OJ2_第6张图片

(~ ̄▽ ̄)~
如果大家觉得本篇文章对自己有所帮助的话,不妨去我的个人博客---乔治的编程小屋逛逛吧.

你可能感兴趣的:(中国矿业大学2021学年算法设计与分析实验课OJ2)