湘潭大学2018年上学期程序设计实践模拟考试2 参考题解

今天状态很差,各种卡手,仰望能够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(N*N*N)

然后对于每个点a,我们判断a能到达多少点,用cnt1计数;
同时计算一下有多少点能到达a,用cnt2计数,
如果cnt1+cnt2==n-1 && cnt1==cnt2
说明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;
}

转载请注明出处~~

猜你喜欢

转载自blog.csdn.net/mmingfunnytree/article/details/80696847