《程序設計語言綜合設計》第二周上機練習


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個數的中位數得證。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM