1. 程式人生 > 其它 >2021年OI集訓隊賽前模擬5題解

2021年OI集訓隊賽前模擬5題解

T1 保齡球大賽 思維

分1.把中立的人加到兩個團體平均。2.加到人少的那一隊這兩種情況
當然也可以按照資料的範圍去分類,即a大於b,a小於b,a等於b三種情況
其他題解請參考 luogu題解

T2 Base64編碼 模擬

我們可以按照三個字元一分隔,中間過程即進位制轉換,ASCII碼為256進位制,Base64編碼為64進位制。
比如Web轉換V2Vi的過程,其ASCII值分別為87,101,98。然後把當成256進位制數,也就是x=87256256+102*256+98。得到x之後,要將其轉換為64進位制數,最低位可以%64得到,倒數第2位可以/64%64得到,倒數第3位可以/64/64%64得到,倒數第4位(最高位)可以/64/64/64得到,此數位下標,對應找到表裡的值即可。然後將這個步驟轉換為程式碼。
=號的話長度還剩1或2,特判即可。

T3 說無可說 DFS

這次就屬於T4比T3難的情況,比賽一般情況下難度從前往後,但是也存在不是這樣的情況,所以每個題都要閱讀。
出題人的題解:
“對於30%的資料,字串的總長度<=5000”
DP,列舉兩個串A和B,設f[i][j]表示A中以第i位開始的字串變成B中以第j為開始的字串的最小次數
“對於40%的資料,字串的總長度<=12000”
跟30%的一樣,陣列滾動就好了。
“對於60%的資料,字串的總長度<=100000”
所以DP時很多狀態都是無用的,因為如果兩個串的長度差大於8那麼對答案沒有貢獻
“對於另外20%的資料,1<=n<=70”
其實這檔跟正解沒有什麼區別,好像也是可以過掉100分的,沒有實測,但是分分鐘跑的比正解快?!
由於只要求相似度小於等於8 的字串對數,那麼考慮遞迴的計算兩個串的相似度,對於串A和B,假設當前我們已經匹配到x和y(x是A中的位置,y是B中的位置),那麼首先跳過以這兩個位置開頭的LCS,然後三種操作繼續遞迴下去,如果答案大於8就退出。
求LCS的時候就用hash+二分
“對於100%的資料,1<=n<=200,字串的總長度<=1000000”
標程的方法是跳LCS的時候一個個跳...

loj上有很多ac程式碼可以參考

T4 散步 動態規劃

和傳紙條和方格取數類似,不過本題解決的是他兩位置上之差的最大值,那麼取完大之後求絕對值即可。
30分的程式碼(實際上可以得50分),你問我陣列為甚麼不直接開105,我只能說請你算下空間,不然這30都過不去。

#include<bits/stdc++.h>
using namespace std;
int a[51][51],sum[51][51][51][51],n,i,j,h,k,x,y,z;
int main()
{
	freopen("walk.in","r",stdin);
	freopen("walk.out","w",stdout);
	cin>>n;
    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)cin>>a[i][j];
    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
    for(h=1;h<=n;h++)
    for(k=1;k<=n;k++)
    {
        int tmp1=max(sum[i-1][j][h-1][k],sum[i][j-1][h][k-1]);
        int tmp2=max(sum[i-1][j][h][k-1],sum[i][j-1][h-1][k]);
        sum[i][j][h][k]=max(tmp1,tmp2)+abs(a[i][j]-a[h][k]);
    }
    cout<<sum[n][n][n][n];
    return 0;
}

那麼想要優化怎麼辦呢,需要考慮步數,從(1,1)走到(n,n)需要2n-1步,那我們直接列舉步數就可以了,也就是優化為O(n^3)的動態規劃

大佬您太強了,還請多多指教哎