湘潭大學2018年上學期程式設計實踐模擬考試2 參考題解

mMingfunnyTree發表於2018-06-14

這個部落格不再更新,新部落格地址請戳

今天狀態很差,各種卡手,仰望能夠1A 各題的天命之子。
這套是16軟工的期末考試題,題目難度無限接近程設難度。
謹記謝大的教誨,程式碼要美觀,氣氣+1

A Rotate http://172.22.112.249/exam/index.php/problem/exam_read/id/1360/exam_id/161

思路:
聽謝大的,瞎搞吧,轉內圈比轉外圈簡單。
太裸了,也太噁心了,這題能寫一個小時。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int pos[]={6,7,10,11};
int fx[]={6,6,7,10};
int fy[]={10,7,11,11};
int main(){
    int a[55];
    int t;cin>>t;
    while(t--){
        for(int i=1;i<=16;i++){
            scanf("%d",a+i);
        }
        int ans=INT_MIN;
        for(int i=0;i<4;i++){
            ans = max( ans , a[1]+a[2]+a[5]+a[pos[i]]);
            ans = max( ans , a[3]+a[4]+a[8]+a[pos[i]]);
            ans = max( ans , a[9]+a[13]+a[14]+a[pos[i]]);
            ans = max( ans , a[12]+a[15]+a[16]+a[pos[i]]);

            ans = max( ans , a[2]+a[3]+a[fx[i]]+a[fy[i]]);
            ans = max( ans , a[8]+a[12]+a[fx[i]]+a[fy[i]]);
            ans = max( ans , a[14]+a[15]+a[fx[i]]+a[fy[i]]);
            ans = max( ans , a[5]+a[9]+a[fx[i]]+a[fy[i]]);
        }
        cout<<max(ans , a[6]+a[7]+a[10]+a[11])<<endl;
    }
    return 0;
}

B Distance http://172.22.112.249/exam/index.php/problem/exam_read/id/1361/exam_id/161

思路:
暴力肯定超時,複雜度O(N*M)
謝大提供的解法應該複雜度O(NlogN + MlogM + N + M)
講題的時候說了,在此不寫了,這裡有一個複雜度低一丟丟的做法:複雜度O((N+M)*log(N))
對於A序列,我們進行排序。
對於每一個b,用二分查詢找到大於等於b的最小值,然後更新答案。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int n,a[100005],m,b;

int main(){
    int t;cin>>t;
    while(t--){
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            scanf("%d",a+i);
        }
        sort(a+1,a+1+n);
        int ans=2e9+10;
        for(int i=0;i<m;i++){
            scanf("%d",&b);
            int pos = lower_bound(a+1,a+1+n,b)-a;
            if(pos>n)pos=n;
            if(pos>1){
                ans = min(ans,abs(b-a[pos-1]));
            }
            ans = min(ans , abs(b-a[pos]));
        }cout<<ans<<endl;
    }
    return 0;
}

C Min Base http://172.22.112.249/exam/index.php/problem/exam_read/id/1362/exam_id/161

思路:
聽謝大的,暴力來就行。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n;

bool check(ll a,int b){
    int vis[65]={0};
    while(a){
        vis[a%b]++;
        a/=b;
    }
    if(*max_element(vis,vis+b+1)<=1)return 1;
    return 0;
}

int main(){
    int t;cin>>t;
    while(t--){
        cin>>n;
        for(int b=2;;b++){
            if(check(n,b)){
                printf("%d\n",b);break;
            }
        }
    }
    return 0;
}

D Substring http://172.22.112.249/exam/index.php/problem/exam_read/id/1363/exam_id/161

思路:
嘗試了一下複雜度O(T*|S|log|S|26)的做法,由於常數太大了,TLE,
想了一下應該可以把26個字元壓縮一下,說不定能過。
謝大的做法應該是最優解,複雜度O(T
|S|*26)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int vis[256];
int main(){
    char s[2005];
    while(scanf("%s",s+1)!=EOF){
        memset(vis,0,sizeof vis);
        int cnt=0;
        int len=strlen(s+1);
        int ans=0x3f3f3f3f;
        for(int i=1;i<=len;i++){
            if(vis[s[i]]==0){
                cnt++;
            } vis[s[i]]=i;
            if(cnt==26){
                int dis=INT_MIN;
                for(int j='a';j<='z';j++){
                    dis=max(dis , i-vis[j]+1);
                }
                ans = min( ans , dis);
            }
        }
        if(cnt<26)ans=0;
        cout<<ans<<endl;
    }
    return 0;
}

E Ball http://172.22.112.249/exam/index.php/problem/exam_read/id/1364/exam_id/161

思路:
floyd求一下多源最短路,或者用拓撲排序也能做。
由於給的n很小,floyd程式碼較簡單,沒必要寫拓撲排序。

首先初始化dis矩陣,dis[i][j]表示從i到j的最短路。
然後建邊,對於m次稱重,我們把a比b重認為是a能到達b,b不能到達a,
所以建立有向邊。

跑一邊floyd,複雜度O(NNN)

然後對於每個點a,我們判斷a能到達多少點,用cnt1計數;
同時計算一下有多少點能到達a,用cnt2計數,
如果cnt1+cnt2n-1 && cnt1cnt2
說明a點是中點,如果有多箇中點,輸出0。

提供一下拓撲排序的思路:
設定一個level陣列,每次把入度為0的點壓入佇列,然後記錄它的level,處理完畢之後,得到的level陣列可以直接來判斷中點是否存在以及個數。複雜度是要比floyd低的。(這樣口頭ac,下次謝大要改資料範圍了,氣氣+1)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 100;
const int inf  = 100000;
int n,m,u,v;
int dis[maxn][maxn];

int main(){
    int t;cin>>t;
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(i==j)dis[i][j]=0;
                else dis[i][j]=inf;
            }
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d",&u,&v);
            dis[u][v]=1;
        }
        for(int k=1;k<=n;k++){
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    if(dis[i][k]<inf && dis[k][j]<inf){
                        dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
                    }
                }
            }
        }
        int id=0,ok=1;
        for(int i=1;i<=n;++i){
            int cnt1=0,cnt2=0;
            for(int j=1;j<=n;j++){
                if(i==j)continue;
                if(dis[i][j]<inf){
                    cnt1++;
                }
                else{
                    if(dis[j][i]<inf){
                        cnt2++;
                    }
                }
            }
            if(cnt1+cnt2==n-1){
                if(cnt1==cnt2){
                    if(id)ok=0;
                    else id=i;
                }
            }
        }
        if(ok&&id)printf("%d\n",id);
        else printf("0\n");
    }
    return 0;
}

F Black White Chess http://172.22.112.249/exam/index.php/problem/exam_read/id/1365/exam_id/161

思路:
這次我學乖了,我不亂寫了。
跟上次模考題一樣的,17種狀態。
那麼很簡單的一個bfs,初始壓入0和1<<16-1,它們的step是0。
然後跑個最裸的bfs就過了。

複雜度不好說,反正肯定是不會超時的。如果非要說,那由於狀態只有1<<16種,bfs時不會超過這麼多次,而每次詢問都是O(1)的。
謝老師說了,程式碼要寫的好看,不然不及格。

#include <bits/stdc++.h>
using namespace std;

int vis[1<<16+10];

int multi[]={
    0x0000f000,0x00000f00,0x000000f0,0x0000000f,
    0x00008888,0x00004444,0x00002222,0x00001111,
    0x0000cc00,0x00006600,0x00003300,
    0x00000cc0,0x00000660,0x00000330,
    0x000000cc,0x00000066,0x00000033
};

void bfs(){
    queue<int> q;
    vis[0]=1;vis[(1<<16)-1]=1;
    q.push(0);q.push((1<<16)-1);
    while(!q.empty()){
        int now = q.front();q.pop();
        int val;
        for(int i=0;i<17;i++){
            val = now ^ multi[i];
            if(vis[val])continue;
            vis[val]=vis[now]+1;
            q.push(val);
        }
    }
}

int main(){
    bfs();
    int k;scanf("%d",&k);
    char s[100];
    while(k--){
        scanf("%s",s);
        int val1=0;
        for(int i=0;i<16;i++){
            if(s[i]=='1')val1+=(1<<i);
        }
        printf("%d\n",vis[val1]-1);
    }
    return 0;
}

轉載請註明出處~~

相關文章