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

1,231 阅读9分钟

1.Contest2411 - 毕老师算法A作业一

传送门在这里 题目总览:

A.进制转换

 #include<iostream>
 using namespace std;
 long Revert(long x)
 {
     long ans = 0;
     long mutiply = 1;
     while(x)
     {
         ans += ((x%8) * mutiply);
         mutiply *= 10;
         x /= 8;
     }
     return ans;
 }
 int main()
 {
     int x, ans;
     cin>>x;
     ans = Revert(x);
     cout<<ans<<endl;
     return 0;
 }

B.排列问题

 // B.排列问题
 #include<bits/stdc++.h> //奇怪之处就在于基本上所有的代码只要用了这个头文件就不再写其他头文件了。
 using namespace std;  
 vector<string> ans;
 void Perm(string str, int low, int high)
 {
     if(low == high)
     {
         ans.push_back(str);
         return;
     }
     for(int i=low; i<=high; ++i)
     {
         if(i>0 && str[i]==str[i-1]) continue;  //判断重复
         swap(str[i], str[low]);
         Perm(str, low+1, high);
         swap(str[i], str[low]);
     }
 }
 int main()
 {
     string str;
     cin>>str;
     str.pop_back();
     sort(str.begin(), str.end());
     Perm(str, 0, str.size()-1);
     sort(ans.begin(), ans.end());
     for(const auto x:ans) cout<<x<<" ";
     system("pause");
     return 0;
 }

C.快速幂

 #include<bits/stdc++.h>
 using namespace std;
 const long long mm = 100000007;
 typedef long long ll;
 ll mostfastPow(ll base, ll power)
 {
     ll result = 1;
     while(power>0)
     {
         if(power&1)
         {
             power = power - 1;
             result = result * base % mm;
         }
         power >>= 1;
         base = base * base % mm;
     }
     return result;
 }
 ll myPow(int x)
 {
     ll ans = 0;
     for(int i=1; i<=x; ++i)
     {
         ans += mostfastPow(i, i);
     }
     return (ans+1)%mm;
 }
 int main()
 {
      int x;
      while(scanf("%d", &x))
     {
        cout<<myPow(x)<<endl;
     }
     return 0;
 }
 // 参考文章:https://blog.csdn.net/qq_19782019/article/details/85621386?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163080391116780261989580%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=163080391116780261989580&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-85621386.first_rank_v2_pc_rank_v29&utm_term=%E5%BF%AB%E9%80%9F%E5%B9%82&spm=1018.2226.3001.4187

D.求第k小

 // D.求第k个小的数
 #include<bits/stdc++.h>
 using namespace std;
 int Partition(int a[], int low, int high);
 template<class Type>
 int RandomizedPartition(Type a[], int p, int r);
 template<class Type>
 void RandomizedQuickSort(Type a[], int p, int r);
 template<class Type>
 Type RandomizedSelect(Type a[], int p, int r, int k);
 int main()
 {
     int a[100], n;
     while(~scanf("%d", &n))
     {
         memset(a, 0, sizeof(a));
         for(int i=0; i<n; i++) scanf("%d",&a[i]);
         int k;
         scanf("%d", &k);
         cout<<RandomizedSelect(a, 0, n-1, k)<<endl;
     }
     system("pause");
     return 0;
 }
 ​
 // 2.RandomizedSelect,平均时间复杂度O(n)
 int Partition(int a[], int low, int high)
 {
     int key = a[low];
     while(low<high)
     {
         while(low<high&&a[high]>key) --high;
         a[low] = a[high];
         while(low<high&&a[low]<=key) ++low;
         a[high] = a[low];
     }
     a[low] = key;
     return low;
 }
 template<class Type>
 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<class Type>
 // void RandomizedQuicksort(Type a[], int p, int r)  //随机快排
 // {
 //     if(p<r)
 //     {
 //         int q = RandomizedPartition(a, p, r);
 //         RandomizedQuicksort(a, p, q-1); //对左半段排序
 //         RandomizedQuicksort(a, q+1, r); //对右半段排序
 //     }
 // }
 template<class Type>
 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:loc]中的元素个数
     if(k<=count) return RandomizedSelect(a, p, loc, k);
     else return RandomizedSelect(a, loc+1, r, k-count);
 }

E.沙子的质量

 #include<bits/stdc++.h>
 using namespace std;
 const int inf=0x3f3f3f3f;
 int a[1005],sum[1005]={0};
 int f[1005][1005];
 ​
 int main()
 {
     int n;
     cin>>n;
     for(int i=1;i<=n;i++){
         cin>>a[i];
     }
     //初始化赋值为最大值
     memset(f,inf,sizeof(f));
     for(int i=1;i<=n;i++){
         f[i][i]=0;
         sum[i]=sum[i-1]+a[i];
     }
     //区间dp,首先确定区间长度len,区间长度便是动态规划的阶段。
     for(int len=2;len<=n;len++){     //阶段:区间长度len
         for(int L=1;L<=n-len+1;L++){ //状态左端点L取值范围
             int r=L+len-1;           //区间右端点r
             for(int k=L;k<r;k++){ //决策,连接点k
                 f[L][r]=min(f[L][k]+f[k+1][r]+sum[r]-sum[L-1],f[L][r]);
             }
         }
     }
     cout<<f[1][n]<<endl;
     system("pause");
     return 0;
 }

F.最长公共子序列

 // F.最长公共子序列
 #include<bits/stdc++.h>
 using namespace std;
 int longestCommonSubsequence(string a, string b)
 {
     int M = a.size();
     int N = b.size();
     vector<vector<int>> dp(M+1, vector<int>(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<<longestCommonSubsequence(a, b)<<endl;
     system("pause");
     return 0;
 }

G.sort

 // Sort
 #include<bits/stdc++.h>
 using namespace std;
 const int Maxn = 1000001;
 int a[Maxn];
 int main()
 {
     int n, m;
     while(~scanf("%d%d", &n, &m))
     {
         memset(a, 0, sizeof(a));
         for(int i=0; i<n; ++i)
         {
             int t;
             scanf("%d", &t);
             a[500000 + t] = 1;
         }
         for(int i=Maxn; m>0; --i)
         {
             if(a[i])
             {
                 if(m>1) printf("%d ", i-500000);
                 else printf("%d\n", i-500000);
                 m--;
             }
         }
     }
     return 0;
 }

H.Joseph

 // 约瑟夫环
 #include<bits/stdc++.h>
 using namespace std;
 const int maxn = 15;
 int num[maxn];
 int main()
 {
     for(int i=1; i<=14; ++i)
     {
         int m = i+1;  //报号数从i+1开始
         int sum = i*2;  //总人数sum
         int j,pre=0,cur=0;  //pre表示之前杀死的一个人,cur表示当前杀死的人的位置
         for(j = 0 ; j < i ; ++j) //一共要杀死i个人
         {
             cur = (pre+m-1)%(sum-j);   //sum-j表示剩余的人数//  牢记此表达式! cur = (pre+m-1)%(sum-j)
             if(cur<i)  //杀到了好人,重置所有变量,报号数++
             {
                 j=-1;   //如果for循环中j初始为0的话,此处应该j为-1,因为马上就要++j了
                 pre=0;
                 cur=0;
                 m++; 
             }
             pre=cur;
         }
         num[i] = m;  //记录答案
     }
     int k;
     while(scanf("%d",&k)!=EOF,k)
         printf("%d\n",num[k]);
 }

I.Factstone Benchmark

 // Factstone等级被定义为这样的最大整数n,使得n!可以表示为一个计算机字中的无符号整数(比如1960年的4位计算机可表示3!=6,而不能表示4!=24)。
 // n! < pow(2, m) m为多少位计算机,求出最大的n值
 // 使用对数计算 ln(n!) < mlog(2) 大大减少数值 即ln(n)+ln(n-1)+...+ln(1) < mln(2)
 #include<bits/stdc++.h>
 using namespace std;
 int Rating(int year)
 {
     int m = pow(2, (year-1940)/10);
     cout<<m<<endl;
     double ans = 0;
     int n = 1;
     while(ans<m*log(2))
     {
         ans += log(n);
         cout<<"ans:"<<ans<<endl;
         n++;
     }
     return n-2;
 }
 int main()
 {
     int year;
     while(cin>>year)
     {
         if(year==0) break;
         cout<<Rating(year)<<endl;
     }
     cout<<log(2)<<endl;
     system("pause");
     return 0;
 }
 ​
 //打表法
 #include <stdio.h>
 #include <cmath>
 /*int main(){
     double sum;
     for (int i = 4, j = 0; j <= 20; i *= 2, j++){
         int k = 1;
         sum = 0;
         while (sum < i){
             sum += log2(k);
             k++;
         }
         printf("%d\n", k - 2);
     }
 }*/
 int main(){
     int year;
     int ans[21] = { 3, 5, 8, 12, 20, 34, 57, 98, 170, 300, 536, 966, 1754,
         3210, 5910, 10944, 20366, 38064, 71421, 134480, 254016 };
     while (scanf("%d", &year) && year != 0){
         getchar();
         year = (year - 1960) / 10;
         printf("%d\n", ans[year]);
     }
     return 0;
 }
  

J.Ants

 // J.Ants
 // 我傻了,很简单的问题:蚂蚁相遇之后往相反方向走,其实并没有什么影响,因为蚂蚁若是按照原方向走本来还是要走这么远,只是换了一只蚂蚁走而已.
 // 我们不必要关心具体的蚂蚁,不管它相遇不相遇,其实结果就是一样的,我们可以认为是保持原样交错而过
 #include<iostream>
 #include<algorithm>
 using namespace std;
 int main()
 {
     int num;
     cin>>num;
     while(num--)
     {
         int len,n;
         int max1=0,min1=0;
         cin>>len>>n;
         for(int i=0;i<n;i++)
         {
             int pos;
             cin>>pos;
             max1 = max(max1, max(pos, len-pos));   //找每只蚂蚁距离两端的最大值max(pos, len-pos),在这些最大值里面找到最大的
             min1 = max(min1, min(pos, len-pos));  //找每只蚂蚁距离两端的最小值min(pos, len-pos),在这些最小值里面找到最大的
         }
         cout<<min1<<" "<<max1<<endl;
     }
     system("pause");
     return 0;
 }

K.Matches Game

 // Bouton定理:先手能够在非平衡尼姆博弈中取胜,而后手能够在平衡的尼姆博弈中取胜。
 // 具体解释请访问: [乔治的编程小屋---尼姆博弈](http://www.pgcode.top/2021/09/16/%e5%b0%bc%e5%a7%86%e5%8d%9a%e5%bc%88/)
 #include<iostream>
 using namespace std;
 int main()
 {
     int n, a;
     while(scanf("%d", &n)!=EOF)
     {
         int ans = 0;
         for(int i=0; i<n; ++i)
         {
             scanf("%d", &a);
             ans ^= a;
         }
         if(ans) printf("Yes\n");
         else printf("No\n");
     }
     system("pause");
     return 0;
 }

L.Sort2

 // Sort2
 #include<bits/stdc++.h>
 using namespace std;
 const int Maxn = 1000001;
 int a[Maxn];
 int main()
 {
     int n, m;
     while(~scanf("%d%d", &n, &m))
     {
         for(int i=0; i<n; ++i)
         {
             int t;
             scanf("%d", &t);
             a[500000+t]++;
         }
         for(int i=Maxn; m>0; --i)
         {
             if(a[i])
             {
                 for(int j=0; j<a[i]; ++j)
                 {
                     if(m>1) printf("%d ", i-500000);
                     else printf("%d\n", i-500000);
                     m--;
                 }
             }
         }
     }
     return 0;
 }

2.Contest2417 - 毕老师算法A作业二

传送门在这里 题目总览:

A.单词排序

 // A.单词排序
 #include<iostream>
 #include<vector>
 #include<string>
 #include<algorithm>
 using namespace std;
 int main()
 {
     int n;
     cin>>n;
     vector<string> vec;
     string str;
     for(int i=0; i<n; ++i)
     {
         cin>>str;
         vec.push_back(str);
     } 
     sort(vec.begin(), vec.end());
     for(const auto x:vec) cout<<x<<" ";
     system("pause");
     return 0;
 }

B.求数组的最长递减子序列

 // B.求数组的最长递减子序列(注意不是不递增序列)
 #include<iostream>
 #include<vector>
 #include<algorithm>
 using namespace std;
 // DP
 int PosOfLDS(vector<int> &nums, vector<int> &memo)  //返回最长递减子序列最后一个元素的下标,然后
 {
     int n = nums.size();
     if(n == 0) return 0;
     vector<int> dp(n, 1);
     // vector<int> memo(n, -1);
     for(int i=0; i<n; ++i)
     {
         for(int j=0; j<i; ++j)
         {
             if(nums[i] < nums[j])
             {
                 dp[i] = max(dp[j]+1, dp[i]);
                 memo[i] = j;
             }
         }
     }
     for(const int x:dp) cout<<x<<" ";
     cout<<endl;
     for(const int x:memo) cout<<x<<" ";
     cout<<endl;
     // return *max_element(dp.begin(), dp.end());  //记住不是return最后一个dp[n-1]!!!
     return max_element(dp.begin(), dp.end()) - dp.begin();
 }
 void PrintOfLDS(vector<int> &nums, vector<int> &memo, int pos)
 {
     if(memo[pos] == -1) 
     {
         cout<<nums[pos]<<" ";
         return;
     }
     else 
     {
         PrintOfLDS(nums, memo, memo[pos]);
         cout<<nums[pos]<<" ";
     }
 }
 int main()
 {
     int n;
     while(~scanf("%d", &n))
     {
         vector<int> nums(n);
         for(int i=0; i<n; ++i) scanf("%d", &nums[i]);
         // cout<<LengthOfLDS(nums)<<endl;
         vector<int> memo(n, -1);
         int max_pos = PosOfLDS(nums, memo);
         PrintOfLDS(nums, memo, max_pos);
     }
     system("pause");
     return 0;
 }
 ​
 // // 方法二.找出与降序排好的数组的最长公共子序列
 // const int Size = 1010;   //尽量用全局变量
 // int DP[Size][Size];
 // int DIR[Size][Size];    
 // bool compare(int a, int b)  //降序排列
 // {
 //     return a>b;
 // }
 // int LCS_length(vector<int> &a, vector<int> &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(vector<int> &a, int i, int j)
 // {
 //     if(i==0 || j==0) return;
 //     if(DIR[i][j] == 1) 
 //     {
 //         LCS(a, i-1, j-1);
 //         cout<<a[i-1];  //a[i-1]==b[j-1]
 //     }
 //     else if(DIR[i][j]==2) LCS(a, i-1, j);
 //     else if(DIR[i][j]==3) LCS(a, i, j-1);
 // }
 // int main()
 // {
 //     int n;
 //     while(scanf("%d", &n) && n)
 //     {
 //         int a[n], b[n];
 //         for(int i=0; i<n; i++) 
 //         {
 //             scanf("%d", a+i);
 //             b[i] = a[i];
 //         }
 //         for(int i=0; i<n; i++) cout<<a[i];
 //         cout<<endl;
 //         for(int i=0; i<n; i++) cout<<b[i];
 //         cout<<endl;
 //         sort(a, a+n, compare);
 //         for(int i=0; i<n; i++) cout<<a[i];
 //         cout<<endl;
 //         vector<int> A(a, a+n), B(b, b+n);
 //         cout<<LCS_length(A, B)<<endl;
 //         LCS(A, n, n);
 //         cout<<endl;
 //     }
 //     system("pause");
 //     return 0;
 // }

C.矩形滑雪场

 #include <iostream>
 #include <vector>
 using namespace std;
 const int maxn = 100;
 int r, c;
 int max_len[maxn][maxn], mp[maxn][maxn];
 ​
 int get_len(int i, int j) {
     if (max_len[i][j]) {
         return max_len[i][j];
     }
     int max_neighbor = 0;
     if (i-1 >= 0 && mp[i][j] > mp[i-1][j]) {
         max_neighbor = max(max_neighbor, get_len(i-1, j));
     }
     if (i+1 < r && mp[i][j] > mp[i+1][j]) {
         max_neighbor = max(max_neighbor, get_len(i+1, j));
     }
     if (j-1 >= 0 && mp[i][j] > mp[i][j-1]) {
         max_neighbor = max(max_neighbor, get_len(i, j-1));
     }
     if (j+1 < c && mp[i][j] > mp[i][j+1]) {
         max_neighbor = max(max_neighbor, get_len(i, j+1));
     }
     max_len[i][j] = max_neighbor + 1;
     return max_len[i][j];
 }
 int main() {
 //  freopen("test.txt", "r", stdin);
     cin >> r >> c;
     int i, j;
     for (i=0; i<r; ++i) {
         for (j=0; j<c; ++j) {
             cin >> mp[i][j];
         }
     }
     int res = 0;
     for (i=0; i<r; ++i) {
         for (j=0; j<c; ++j) {
             res = max(res, get_len(i, j));
         }
     }
     cout<<res<<endl;
 }

D.Homework

 #include<bits/stdc++.h>
 using namespace std;
 bool cmp(pair<double, double> a, pair<double, double> b)
 {
     return a.second/a.first > b.second/b.first;
 }
 int main()
 {
     int M, N;
     while(scanf("%d%d", &M, &N) && (M && N))
     {
         vector<pair<double, double>> vec;
         double time, value;
         for(int i=0; i<M; ++i)
         {
             scanf("%lf%lf", &time, &value);
             vec.push_back(pair<double, double>(time, value));
         }   
         sort(vec.begin(), vec.end(), cmp);
         double TimeTotal = N;
         double ValueTotal = 0;   //double类型,如果写为int类型答案错误
         for(const auto x:vec) cout<<"("<<x.first<<","<<x.second<<")"<<endl;
         for(const pair<double, double> x:vec)
         {
             if(TimeTotal-x.first >= 0)
             {
                 cout<<"Flag1"<<endl;
                 ValueTotal += x.second;
                 TimeTotal -= x.first;
             }
             else 
             {
                 ValueTotal += TimeTotal * x.second/x.first;
                 break;
             }
         }
         printf("%.2lf\n", ValueTotal);
     }
     system("pause");
     return 0;
 }

E.区间包含问题

 // E.区间包含问题
 // 贪心算法  类似于活动安排问题
 #include<bits/stdc++.h>
 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<n; ++i) 
     {
         scanf("%d %d", &node[i].left, &node[i].right);
         // node[i].right++;
     }
     sort(node, node+n, cmp);
     int l, r;
     for(int i=0; i<m; ++i) 
     {
         scanf("%d %d", &l, &r);
         int pos = l, ans = 0;
         for(int j=0; j<n; ++j)
         {
             if(node[j].left>=pos && node[j].right<=r)
             {
                 cout<<l<<" "<<r<<endl;
                 cout<<j<<" "<<node[j].left<<" "<<node[j].right<<endl;
                 ans++;
                 pos = node[j].right;
             }
         }
         printf("%d\n", ans);
     }
     system("pause");
     return 0;
 }

F.最长子序列

 // F.最长子序列(最大子段和)
 #include<bits/stdc++.h>
 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<int> &nums)
 {
     int n = nums.size();
     if(n==0) return {};
     if(n==1) return nums[0];
     vector<int> f(n);
     f[0] = nums[0];
     for(int i=1; i<n; ++i)
     {
         f[i] = max(f[i-1]+nums[i], nums[i]);
     } 
     for(const int x:f) cout<<x<<" ";
     cout<<endl;
     return *max_element(f.begin(), f.end());  //记住不是返回f[n-1]
 }
 int maxSubArray2(vector<int> &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<int> nums(n);
         for(int i=0; i<n; ++i) scanf("%d", &nums[i]);
         cout<<maxSubArray(nums)<<endl;
     }
     system("pause");
     return 0;
 }

G.元素整除问题

 // G.元素整除问题
 #include<bits/stdc++.h>
 using namespace std;
 // O(n^2)
 int main()
 {
     int a[20];
     for(int i=0; i<20; i++) scanf("%d", &a[i]);
     sort(a, a+20);
     for(int i=1; i<20; i++)
     {
         for(int j=0; j<i; j++)
         {
             if(a[i]%a[j] == 0)
             {
                 printf("%d\n", a[i]);
                 break;
             } 
         }
     }
     system("pause");
     return 0;
 }

H.渊子赛马

  // H.渊子赛马
 #include<bits/stdc++.h>
 using namespace std;
 int main()
 {
     int n;
     while(scanf("%d", &n) && n)
     {
         int *a = new int[n], *b = new int[n];
         for(int i=0; i<n; ++i) scanf("%d", &a[i]);
         for(int i=0; i<n; ++i) scanf("%d", &b[i]);
         sort(a, a+n);
         sort(b, b+n);
         int count = 0;
         int pos = 0;
         for(int i=0; i<n; ++i)
         {
             for(int j=pos; j<n; ++j)
             {
                 if(a[j]>b[i])   //找到一个最近的大于b[i]的
                 {
                     count++;
                     pos = j;
                     cout<<"count:"<<count<<"  pos:"<<pos<<" a[j]:"<<a[j]<<" b[i]:"<<b[i]<<endl;
                     break;  
                 }
             }
             if(pos==n-1) break;
         }
         if(count > n/2) printf("YES\n");
         else printf("NO\n");
     }
     system("pause");
     return 0;
 }

I.The hardest problem ever

 // I.ż•ČöĂÜÂë
 #include<bits/stdc++.h>
 using namespace std;
 int main()
 {
     freopen("I_in.txt","r",stdin);
     freopen("I_out2.txt","w",stdout);
     // string model = "VWXYZABCDEFGHIJKLMNOPQRSTU";
     string str;
     while(cin>>str)
     {
         if(str=="ENDOFINPUT") break;
         if(str=="START") continue;
         if(str=="END") 
         {
             printf("\n");
             continue;
         }
         for(int i=0; i<str.length(); ++i)
         {
             // if(isalpha(str[i])) str[i] = model[(str[i]-'A')%26];
             if(isalpha(str[i])) str[i] = 'A' + (str[i]-'A'+21)%26;
         }
         cout<<str<<" ";
     }
     system("pause");
     return 0;
 }

J.Rock-Paper-Scissors Tournament

 // J.Rock-Paper-Scissors Tournament
 #include<algorithm>
 #include<iostream>
 #include<cstring>
 using namespace std;
 #define mm(a) memset(a, 0, sizeof(a));
 int i, j, n, k;
 string s;
 int t = 0;
 int win[105] = {0};
 int lose[105] = {0};
 int main()
 {
     // freopen("J_in.txt", "r", stdin);
     // freopen("J_out.txt", "w", stdout);
     while(1)
     {
         scanf("%d%d", &n, &k);
         if(n==0) break;
         mm(win); mm(lose);
         if(t++) printf("\n");
         for(i=0; i<k*n*(n-1)/2; ++i)
         {
             int p1 = 0, p2 = 0;
             char s1[10]={0}, s2[10]={0};
             scanf("%d %s %d %s", &p1, s1, &p2, s2);
             if(s1[0]==s2[0]) continue;
             else if(s1[0]=='r'&&s2[0]=='s' || s1[0]=='s'&&s2[0]=='p' || s1[0]=='p'&&s2[0]=='r')
                 {win[p1]++, lose[p2]++;}
             else 
                 {win[p2]++, lose[p1]++;}
         }
         for(int i=1; i<=n; ++i)
         {
             if(win[i]+lose[i]) printf("%d: %.3f\n", i, 1.0*win[i]/(win[i]+lose[i]));
             else printf("-\n");
         }
     }
     return 0;
 }

K.Balloon Robot

 // K.Balloon Robot
 #include<bits/stdc++.h>
 using namespace std;
 /*
 假设初始机器人从位置1开始,计算做完每道题总共有多少不开心值
 将不开心值从小到大排序
 然后枚举每一道题解出时,机器人就在座位旁的情况。
 对于第i道题目,因为位置往后走,后面的题目的时间就会减少tid[i],前面的题目的时间就会增加m-tid[i].
 因此递推式是sum - (p-i)*tid[i] + i*(m-tid[i])
           = sum + m * (i - 1) - tid[i] * p;
 */
 typedef long long ll;
 const int N = 2e5+10;
 ll tid[N], id[N]; //id数组用来记录每个队伍所在的位置
 int main()
 {
     freopen("K_in.txt","r",stdin);
     int t;
     scanf("%d", &t);    //测试用例组数
     while(t--)
     {
         ll n, m, p;
         scanf("%lld%lld%lld", &n, &m, &p); //n个队伍,m个位置,一共解决了p个题目
         for(int i=1; i<=n; ++i)
             scanf("%lld",&id[i]); //n个队伍分别在哪几个位置
         ll ans=1e18, sum = 0;
         for(int i=1; i<=p; i++)
         {
             ll a,b;
             scanf("%lldlld", &a, &b);
             tid[i] = (id[a]-1-b+m)%m; //计算不开心值,不开心值=位置a-第一个位置-AC的时间
             sum += tid[i];
         }
         sort(tid+1, tid+p+1);
         for(int i=1; i<=p; ++i)
             ans = min(ans, sum+m*(i-1)-tid[i]*p);   //sum = sum-(p-i)*tid[i]+i*(m-tid[i]) = sum+m*(i-1)-tid[i]*p
         printf("%lld\n", ans);
     }
 }

2.Contest2420 - 毕老师算法A作业三

传送门在这里 题目总览:

A.Brackets Sequence

 #include<iostream>
 #include<cstdio>
 #include<cstring>
 #include<cmath>
 #define INF 0x3f3f3f3f
 using namespace std;
 int f[105][105],pos[105][105];
 char s[105];
 void fun(int x,int y)
 {
     if(x>y) return;
     if(x==y){
         if(s[x]=='('||s[x]==')') printf("()");
         if(s[x]=='['||s[x]==']') printf("[]");
     }
     else if(x<y){
         if(pos[x][y]==-1){
             if(s[x]=='('){
                 printf("(");
                 fun(x+1,y-1);
                 printf(")");
             }
             else{
                 printf("[");
                 fun(x+1,y-1);
                 printf("]");
             }
         }
         else{
             fun(x,pos[x][y]);
             fun(pos[x][y]+1,y);
         }
     }
 }
 int main()
 {
     scanf("%s",s);
     memset(f,0,sizeof(f));
     int len=strlen(s);
     for(int i=len;i>0;i--){
         s[i]=s[i-1];
         f[i][i]=1;
     }
     for(int l=1;l<=len;l++){
         for(int i=1;i<=len-l;i++){
             int j=l+i;
             f[i][j]=INF;
             if((s[i]=='('&& s[j]==')')||(s[i]=='['&&s[j]==']')){
                 if(f[i+1][j-1]<f[i][j]) f[i][j]=f[i+1][j-1];
             }
             pos[i][j]=-1;
             for(int k=i;k<j;k++){
                 if(f[i][k]+f[k+1][j]<f[i][j]){
                     f[i][j]=f[i][k]+f[k+1][j];
                     pos[i][j]=k;
                 }
             }
         }
     }
     fun(1,len);
     printf("\n");
     return 0;
 }

B.Dollars

 // B.Dollars
 #include<bits/stdc++.h>
 using namespace std;
 int money[] = {1, 2, 4, 10, 20, 40, 100, 200, 400, 1000, 2000};  //除以五,1美元等于100美分
 const int N = 6010;
 long long f[N];
 int main()
 {
     std::ios::sync_with_stdio(false);
     cin.tie(NULL);
     cout.tie(NULL);
 ​
     // 打表法
     f[0] = 1;
     for(int i=0; i<=10; i++)
         for(int j=money[i]; j<=6000; j++)
             f[j] += f[j-money[i]];
     double ans;
     while(cin>>ans && ans!=0)
     {
         int pos = (ans*100)/5;
         printf("%6.2lf%17lld\n", ans, f[pos]);
     }
     return 0;
 }

C.Longest Match

 // C.Longest Match
 #include<bits/stdc++.h>
 using namespace std;
 vector<string> split(string str)  //将一个字符串从空格处分开,非字符也算作空格
 {
     vector<string> vec;
     int len = str.length();
     bool flag = true; //表示一个新单词开始与否
     int start = 0; //每个单词开始的下标
     for(int i=0; i<len; ++i)
     {
         if(flag && isalpha(str[i]))
         {
             flag = false;
             start = i;
         }
         else if(!isalpha(str[i]))
         {
             flag = true;
             vec.push_back(str.substr(start, i-start));
         }
     }
     if(flag == false) vec.push_back(str.substr(start, len-start)); //最后一个为字母的话
     return vec;
 }
 int LongestMatch(vector<string> &vec1, vector<string> &vec2)
 {
     int len1 = vec1.size(), len2 = vec2.size();
     int ans = 0;
     for(int i=0; i<len2; ++i)
     {
         if(find(vec1.begin(), vec1.end(), vec2[i]) != vec1.end()) ans++;
     }
     return ans;
 }
 int main()
 {
     string str1, str2;
     int i = 1;
     while(getline(cin, str1) && getline(cin, str2))
     {
         if(str1.empty() || str2=="") 
         {
             printf("%2d. ",i++);
             cout<<"Blank!"<<endl;
             continue;
         }
         vector<string> vec1, vec2;
         vec1 = split(str1);
         vec2 = split(str2);
         printf("%2d. ",i++);
         cout<<"Length of longest match: "<<LongestMatch(vec1, vec2)<<endl;
     }
     // getline(cin, str1);
     // vector<string> vec1 = split(str1);
     // for(const auto x:vec1) cout<<x<<endl;
     // cout<<endl;
     system("pause");
     return 0;
 }
 ​

D.History Granding

 #include<bits/stdc++.h>  
 using namespace std;
 int order[30];
 int node[30],arry[30][30];
 int main()
     {
         int num;
         cin>>num;
         int i,j,k;
         for(i=0;i<num;i++)
             {
                 cin>>k;
                 order[k-1]=i+1;
             }
         while(cin>>k)
             {
                 node[k-1]=1;
                 for(i=1;i<num;i++)
                     {
                         cin>>k;
                         node[k-1]=i+1;
                     }
                 memset(arry,0,sizeof(arry));
                 for(i=1;i<=num;i++)
                     {
                         for(j=1;j<=num;j++)
                             {
                                 if(node[i-1]==order[j-1]) arry[i][j]=arry[i-1][j-1]+1;
                                 else arry[i][j]=max(arry[i-1][j],arry[i][j-1]);
                             }
                     }
                 cout<<arry[num][num]<<endl;
             }
         return 0;
     }

E.滑雪

 #include<iostream>
 #include<stdio.h>
 #include<algorithm>
 using namespace std;
     int n ,m;
 struct node{
     int x;
     int y;
     int data;
 };
  
 bool cmp(node a, node b){
     return a.data < b.data;
 }
  
 bool check(int x, int y){
     if( x >= 1 && y >= 1 && x <= n && y <= m)
         return 1;
     else
         return 0;
 }
  
 int main (){
  
     int high[105][105];
     int maxLen[105][105];
     int to[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
     int ans = 1;
     cin >> n >> m;
     int k = 0;
     node s[10006];
     for(int i = 1; i <= n; i++){
         for(int j = 1; j <= m; j++){
             scanf("%d", &high[i][j]);
             s[++k].data = high[i][j];
             s[k].x = i;
             s[k].y = j;
             maxLen[i][j] = 1;
         }
     }
     sort(s + 1, s + k + 1, cmp);
     for(int i = 1 ; i <= k; i++){
         int x1, y1;
         
         for(int j = 0; j < 4; j++){
             int x = s[i].x;
             int y = s[i].y;
             x1 = x + to[j][0];
             y1 = y + to[j][1];
             if(check(x1, y1)){
                 if(high[x][y] > high[x1][y1]){
                     maxLen[x][y] = max(maxLen[x1][y1] + 1, maxLen[x][y]);
                     ans = max(ans, maxLen[x][y]);
                 }
             }
         } 
     }
     cout << ans <<  endl;
     return 0;
 }

F.Wavio Sequence

 // Wavio Sequence
 // 贪心算法 + 二分查找 求最长上升子序列的长度  O(nlogn) 
 // 考虑一个简单的贪心,如果我们要使上升子序列尽可能的长,则我们需要让序列上升得尽可能慢,因此我们希望每次在上升子序列最后加上的那个数尽可能的小。
 // 维护一个一维数组B,并且这个数组是动态扩展的,初始大小为1,B[i]表示最长上升子序列长度是i的所有子串中末尾最小的那个数,
 // 我们依次遍历数组 nums 中的每个元素,并更新数组 B 和 len 的值。如果nums[j] > B[len] 则更新 len = len + 1
 // 否则在 B[1...len] 中 找到 B[i-1] < nums[j] <  B[i]的pos值,然后更新B[i] = nums[j]
 #include<bits/stdc++.h>
 using namespace std;
 const int inf = 10000;
 int lengthOfLIS(vector<int> &nums, int end)    //得到数组nums[1..end]的最大上升子序列长度
 {
     int n = nums.size();
     if(n  0) return 0;
     vector<int> B(n+1, 0);
     B[1] = nums[0];
     int len = 1;  //记录最长上升子序列的长度
     for(int i=1; i<end; ++i)
     {
         if(nums[i] > B[len]) B[++len] = nums[i];
         else
         {
             int l = 1, r = len, pos = 0;
             while(l <= r)
             {
                 int mid = (l+r) >> 1;
                 if(B[mid] < nums[i])
                 {
                     pos = mid;
                     l = mid+1;
                 }
                 else r = mid-1;
             }
             B[pos+1] = nums[i];
         }
     }
     return len;
 }
 int Ans(vector<int> &nums)
 {
     int n = nums.size();
     vector<int> LIS_length;
     vector<int> LIS_length_Reverse;
     for(int i=1; i<=n; i++)
         LIS_length.push_back(lengthOfLIS(nums, i));  //i为end,所以i<=n
      reverse(nums.begin(), nums.end());  //反转数组
     for(int i=1; i<=n; i++)
         LIS_length_Reverse.push_back(lengthOfLIS(nums, i));
     for(int i=0; i<n; ++i)
     {
         if(LIS_length[i]) LIS_length[i] = -inf;
         if(LIS_length_Reverse[i]==1) LIS_length_Reverse[i] = -inf;
     }
     int max_ans = 1;
     for(int i=0; i<n; ++i)
         max_ans = max(max_ans, LIS_length[i]+LIS_length_Reverse[n-i-1]-1);
     return max_ans;
 }
 int main()
 {
      int n;
     while(cin>>n && n)
     {
         vector<int> nums(n);
         for(int i=0; i<n; i++) cin>>nums[i];
         cout<<Ans(nums)<<endl;
     }
     return 0;
 }

G.FatMouse's Trade

 #include <cstdio>    
 #include <iostream>
 #include <cstring>
 #include <algorithm>
 using namespace std;
 int N,M;
 struct node{
     int x,y;
     double s;
 }a[1000];
 double cmp(node aa,node bb){
     return aa.s>bb.s;
 }
 int main(){
     double sum,ans;
     while(~scanf("%d %d",&M,&N)){
         if(M==-1&&N==-1) break;
         for(int i=0;i<N;i++){
             scanf("%d %d",&a[i].x,&a[i].y);
             a[i].s=(1.0*a[i].x/a[i].y);
         }
         sort(a,a+N,cmp);
         sum=0.0,ans=0.0;
         for(int i=0;i<N;i++){
             if(sum<=M){
                 if(sum+a[i].y<=M){
                     ans+=a[i].x;
                     sum+=a[i].y;
                 }
                 else{
                     ans+=a[i].s*(M-sum);
                     sum=M;
                 }
                 
             }
             else {
                 break;
             }
         }
         printf("%.3lf\n",ans);
         
     }
     return 0;
 }

H.Schedule

 // Schedule
 // 贪心算法
 // 题目大意:有 N个时间表,他们分别有自己的开始时间和结束时间,
 // 同时,也有很多机器,时间表上的时间是使用机器的时间,然而,
 // 一台机器不能在重复的时间被使用,所以,要完成时间表的任务,可能需要多台机器,
 // 题目要求的就是符合要求的最少机器数和相应时间之和(机器等待的时间也算)。
 #include<bits/stdc++.h>
 using namespace std;
 struct Node
 {
     int T;     
     int flag;      //1表示该节点是开始时间,2表示是结束时间
 }nodes[200000];
 bool cmp(Node &a, Node &b)
 {
     if(a.T != b.T) return a.T<b.T;
     else return a.flag > b.flag;
 }
 int main()
 {
     int x;
     scanf("%d", &x);
     while(x--)
     {
         int count;
         int pos = 0;  //表示节点数组的位置
         int machine = 0;
         int ans_mach = 0;
         long long ans_sum = 0;
         stack<int> endtime;     //结束时刻存放在栈中
         scanf("%d", &count);
         while(!endtime.empty()) endtime.pop();  //保证endtime数组清空
         for(int i=0; i<count; i++)
         {
             scanf("%d", &nodes[pos].T);
             scanf("%d", &nodes[pos+1].T);
             nodes[pos].flag = 1;
             nodes[pos+1].flag = 2;
             ans_sum = ans_sum + (nodes[pos+1].T - nodes[pos].T);  //先把所有工作任务的时间累加
             pos += 2;
         }
         sort(nodes, nodes+pos, cmp);        //从小到大排序
         for(int i=0; i<pos; i++)
         {
             if(nodes[i].flag == 1)
             {
                 machine++;
                 if(!endtime.empty())
                 {
                     int t = endtime.top();
                     endtime.pop();
                     ans_sum += (nodes[i].T - t);  //我们并不关心位于栈顶这个结束时间所对应的开始时间是哪个,因为计算等待时间只需要直到结束时间即可.而且根据大小排序之后,可以保证,新加入的这个开始时间一定可以在任意一台已经有的机器上工作!(因为目前所有的结束时间都是小于该开始时间的,所以这也是一个我们不需要关心(开始_结束)对应的一个原因.)
                 }
             }
             else
             {
                 machine--;
                 endtime.push(nodes[i].T);
             }
             ans_mach = max(ans_mach, machine);  //更新最大机器数
         }
         printf("%d %lld\n", ans_mach, ans_sum);
     }
     system("pause");
     return 0;
 }

I.Gene Assembly

 #include <bits/stdc++.h>
 using namespace std;
 ​
 int n;
 struct p
 {
     int start,end,pos;
 }s[1000];
  
 bool cmp(p a,p b)
 {
     return a.end<b.end;
 }
 int main()
 {
     while(scanf("%d",&n) && n)
     {
         for(int i = 0; i < n; i++)
         {
             s[i].pos = i + 1;
             scanf("%d%d",&s[i].start,&s[i].end);
         }
         sort(s,s+n,cmp);
         int t=0;
         for(int i = 0; i < n; i++)
             if(t<s[i].start)
             {
                 t = s[i].end;
                 printf("%d%c",s[i].pos,(i==n-1)?'\n':' ');
             }
     }
     return 0;
 }

(~ ̄▽ ̄)~

除了几个题因为时间缘故或者是太难了的原因不是自己写的,其余的都是自己的劳动成果.由于最近时间紧张,题解就不写了. 如果大家觉得本篇文章对自己有所帮助的话,不妨去我的个人博客---乔治的编程小屋逛逛吧,相信你会发现更精彩的内容.