《程序设计语言综合设计》第二周上机练习

5 最长公共子串

给定两个字符串a、b,现有k次机会对字符串中的字符进行修改,使修改后两个字符串的最长公共子串最长。每一次修改,可以选择a、b字符串中某一个串的任意位置修改成任意字符。

输入格式

第一行包括一个正整数 k。
第二行和第三行分别输入字符串a、b。(每个串的长度不超过500)

输出格式

输出为一个整数,表示修改后的两个串的最长公共子串长度。

输入样例

5
aaaaa
bbbbb

输出样例

5

Accepted

找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的。而最长公共子序列则并不要求连续。



#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string.h>
using namespace std;
int calculate(string a,string b,int k){ //计算字符串开头开始最长的公共子串
    int pos=0; //已访问位置
    int K=0;//差异
    while(pos<a.size()&&pos<b.size()&&(a[pos]==b[pos]||K<k)){
        if(a[pos]!=b[pos]) K++;
        pos++;
    }
    return pos;
}
        int main(){
            int k;
            int lena,lenb;
            int max=0;
            int i,j;
            int ans=0;
            string a,b;
            cin >>k;
            cin >> a >> b;
            lena=(int)a.size();
            lenb=(int)b.size();
            for(i=0;i<lena;i++){
                for(j=0;j<lenb;j++){
                    max=calculate(a.substr(i),b.substr(j),k); //substr :主要功能是复制子字符串,要求从指定位置开始,并具有指定的长度。
                    if(ans<max) ans=max;
                }
            }
            cout << ans << endl;
            return 0;
        }

6 旋转骰子

玛莎有n个骰子,每个骰子的6个面上都恰好有一个0到9之间的数字,且同一个骰子6个面上的数字不会重复。
现在玛莎将利用这n个筛子来制作新数字。她把n个骰子摆成一排,然后从左到右查看骰子的上表面并读取,即可得到一个新数字。随后她不断的旋转每个骰子的面就可以得到不同的新数字。旋转骰子需要满足以下规则: 1、制作的数字不能包含前导零; 2、制作新数字时不需要使用所有的骰子; 3、使用骰子旋转,无法将数字9转换为数字6,反之亦然。
给定n个骰子,玛莎可以用它们构成从1到x的所有整数。玛莎想知道,对于给定的n个骰子,这个x的最大取值是多少呢?

输入格式

第一行仅一个整数n,表示骰子的数量(1≤n≤3)。
接下来n行,每行包含6个整数a[i][j](0≤a[i][j]≤9),表示第i个骰子的第j个面上的数字。

输出格式

输出一个整数,即最大数x,玛莎可以使用她的骰子构成数字从1到x。如果无法构成1,则输出0。

输入样例

3
0 1 3 5 6 8
1 2 4 5 7 8
2 3 4 6 7 9

输出样例

98

Accepted

#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string.h>
using namespace std;
        int main(){
            int n;
            int i,j,k,t;
            int a[500][500];
            cin >> n;
            for(i=1;i<=n;i++){
                for(j=1;j<=6;j++)
                    cin >> a[i][j];
            }
           //n==1
            if(n==1){
                for(j=1,k=1;j<=6;j++){
                    if(a[1][j]==k) k++;
                }
                k--;
                cout << k << endl;
                return 0;
            }
            //n==2
           if(n==2){
               for(j=1,k=1;j<=6;j++){
                   for(t=1;t<=6;t++)
                   if(a[1][t]==k||a[2][t]==k) k++;
               }
               k--;
               if(k<9){cout << k << endl;return 0;}
               else{
                   for(k=10,j=1;j<=35;j++){
                       for(i=1;i<=6;i++){
                           for(t=1;t<=6;t++)
                           if(a[1][i]*10+a[2][t]==k||a[1][i]+a[2][t]*10==k) k++;
                       }
                   }
                   k--;
                   cout << k << endl;return 0;
               }
           }
            
            if(n==3){
                for(j=1,k=1;j<=6;j++){
                    for(t=1;t<=6;t++)
                    if(a[1][t]==k||a[2][t]==k||a[3][t]==k) k++;
                }
                k--;
                if(k<9){cout << k << endl;return 0;}
                else{
                    for(k=10,j=1;j<=35;j++){
                        for(i=1;i<=6;i++){
                            for(t=1;t<=6;t++) if(a[1][i]*10+a[2][t]==k||a[1][t]+a[2][i]*10==k||a[1][i]*10+a[3][t]==k||a[1][t]+a[3][i]*10==k||a[2][i]*10+a[3][t]==k||a[2][t]+a[3][i]*10==k) k++;
                    
                       }
                    }
                    k--;
                    cout << k << endl;return 0;
                }
            }
            return 0;
        }

7 均等笔

n个人围成一圈,每人有ai支笔。每人可以向左右相邻的人传递笔,每人每次传递一支笔消耗的能量为1。求使所有人获得均等数量的笔的最小能量。

输入格式

第一行一个整数n ,表示人的个数(30%的数据,n<=1000;100%的数据,n<=1e6)。
接下来n行,每行一个整数 ai。

输出格式

输出一个整数,表示使所有人获得均等笔的最小能量。(答案保证可以用64位有符号整数存储)

输入样例

4
1
2
5
4

输出样例

4

Accepted

参考来源:糖果传递
对于每个人,假设他的笔数要经过两类变化:1、从后一个人拿。2、给前一个人,最终的变化结果是变为aver.

  • a[1]-X1+X2=aver X2=X1-(a[1]-aver)
  • a[2]-X2+X3=aver X3=X1-(a[2]+a[1]-2*aver)
    设c[1]=a[1]-aver c[2]=c[1]+a[2]-aver
    则有c[i]=c[i-1]+a[i]-aver
    则有问题|X1|+|X2|+……+|Xn|的和最小每个都可以用X1表示为|X1|+|X1-c[1]|+|X1-c[2]|+……+|X1-c[n-1]|
    绝对值的含义又可以表示数轴上Xi到Ci的距离,所以问题变成了:给定数轴上的n个点,找出一个到他们的距离之和尽量小的点,而这个点就是这些数中的中位数,
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string.h>
using namespace std;
int a[1000005]={0},x[1000005]={0};
        int main(){
            int n;
            long long sum=0,num=0;
            int i=0,j;
            int aver;
            cin >> n;
            for(i=0;i<n;i++){
                cin >> a[i];
                sum+=a[i];
            }
            aver=(int)(sum/n);
            for(i=0;i<n;i++){
                x[i]=x[i-1]-a[i-1]+aver;
            }
            sort(x,x+n);
            j=n/2;
            for(i=0;i<n;i++){
                num+=abs(x[j]-x[i]);
            }
            cout << num << endl;
            return 0;
        }

附:数学证明

在数轴上有n个点,找出一个点x,使得她到各个点的距离和最小。求证:该点表示的数就是这n个数的中位数。如果我们把数轴上的点两两配对,最大的配最小的,次大的配次小的……则到每组点最近的距离的点在这两个点中间,那么

如果有奇数个点,那么显然中间那个点便为所求。
∴该点表示的数是这n个数的中位数得证。

猜你喜欢

转载自www.cnblogs.com/lvhang/p/12386018.html
今日推荐