9-7贝壳笔试,4题AK

num1

第一题
题意:石头剪刀布,已知牛妹和牛牛左手出什么右手出什么,但不知道牛牛会出左手还是右手,我们要求一下牛妹出哪只手赢的胜率高一些
思路:用牛妹的左手和牛牛两只手比较算出赢的场数,再用牛妹的右手和牛牛两只手比较算出赢的场数,判断一下牛妹左手赢的场数多一些还是
右手赢的场数多一些即可。


int check(char s,char t)
{
    if(s=='S'&&t=='J')
        return 1;
    if(s=='J'&&t=='B')
        return 1;
    if(s=='B'&&t=='S')
        return 1;
    return 0;
}
int main()
{
    int n,t;
    char a,b,c,d;
    scanf("%d",&t);
    getchar();
    while (t--)
    {
        scanf("%c %c %c %c",&a,&b,&c,&d);
        getchar();
        int y1=0;
        int y2=0;
        if(check(a,c)==1)
            y1++;
        if(check(a,d)==1)
            y1++;
        if(check(b,c)==1)
            y2++;
        if(check(b,d)==1)
            y2++;
        if(y1==y2)
        {
            printf("same\n");
        }
        else if(y1>y2)
        {
            printf("left\n");
        } else
        {
            printf("right\n");
        }
    }
    return 0;
}

num2

懒得写。

#include<bits/stdc++.h>
using namespace std;
typedef  long long ll;
const int maxn = 3e5 + 10;
char a[maxn];
int main()
{
   int n,t;
   while (~scanf("%d",&n)){
       scanf("%s",a);
       int ans=n;
       int i=0;
       int j=0;
       int k=1;
       while (k<=n/2){
           bool flag=true;
           j=k;
           i=0;
           while (i<k){
               if(a[i++]!=a[j++]) flag=false;
           }
           if(flag)
               ans=min(ans,k+1+n-2*k);
           k++;
       }
       printf("%d\n",ans);
   }
   return 0;
}

num3

题意:给定M种颜色,M*K种不能相邻关系,稳排序方案。
思路:这类题一般都是可以搜索做,而搜索一般都可以退出DP方案,而DP方案可以转化为矩阵乘法的,可以用矩阵乘法来加速。所以这题:搜索<DP<矩阵乘法。这里只讲DP。我们假设dp[i][j]表示第I位为j颜色的方案数,显然dp[i][j]+=dp[i-1][k](j、k可以相邻)

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int maxn=1010;
int dp[maxn][11],mp[11][11];
int main()
{
    int T,N,M,K,x;
    scanf("%d",&T);
    while(T--){
        memset(mp,0,sizeof(mp));
        scanf("%d%d%d",&N,&M,&K);
        for(int i=1;i<=M;i++){
            for(int j=1;j<=K;j++){
                scanf("%d",&x);
                mp[x][i]=1;
            }
        }
        dp[0][0]=1;
        for(int i=1;i<=N;i++){
            for(int j=1;j<=M;j++){
                for(int k=0;k<=M;k++){
                    if(!mp[j][k]) {
                        dp[i][j]+=dp[i-1][k];
                        if(dp[i][j]>=mod) dp[i][j]-=mod;
                    }
                }
            }
        }
        int ans=0;
        for(int i=1;i<=M;i++) {
            ans+=dp[N][i];
            if(ans>=mod) ans-=mod;
        }
        printf("%d\n",ans);
    }
    return 0;
}

num4

为了没负数,我们把下标从-N到N,变为1-2N。然后开始区间DP。我们令dp[i][j]表示杀完[i,j]区间的最小代价,那么一般都可以有dp[i][j]=min(dp[i][j-1]+代价1,dp[i+1][j]+代价2)。
所以我们了没有后续性,我们可以把长度设为第一维。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2010;
int a[maxn],b[maxn],suma[maxn],sumb[maxn],dp[maxn][maxn];
int main()
{
    int T,N,M,K,x;
    scanf("%d",&N);
    memset(dp,0x3f,sizeof(dp));
    for(int i=1;i<=N+N;i++) {
        scanf("%d",&a[i]);
        suma[i]=suma[i-1]+a[i];
    }
    for(int i=1;i<=N+N;i++) {
        scanf("%d",&b[i]);
        sumb[i]=sumb[i-1]+b[i];
    }
    for(int L=1;L<=N+N;L++){
       for(int i=1;i<=N+1;i++){
            int j=i+L-1;
            if(i>N+1||j<N||j>N+N) continue;
            if(i==j) {
                 dp[i][j]=a[i];
            }
            else {
                int x=dp[i+1][j],y=dp[i][j-1];
                int nowx=sumb[j]-sumb[i]-suma[j]+suma[i]+dp[i+1][j];
                int nowy=sumb[j-1]-sumb[i-1]-suma[j-1]+suma[i-1]+dp[i][j-1];
                if(nowx<a[i]) x+=a[i]-nowx;
                if(nowy<a[j]) y+=a[j]-nowy;
                dp[i][j]=min(x,y);

            }
        }
    }
    printf("%d\n",dp[1][N+N]+1);
    return 0;
}
09-09 15:32