9-5 搜狗笔试 AK

9-5搜狗题目,3题AK

第一题

题意:

给你三种道具A,B,C.分别有a个,b个,c个.
可以把其中的任意两个道具(包括两个同一种的)换成任意指定道具.
三种不同的道具各来一个可以换一个奖品.求有多少种奖品

思路:

通过排序,弄成a < b < c
设答案为ans = 0
先合成a个奖品

ans += a
a = 0
b -= a
c -= a

然后再判断 c-2*b > b

如果是的话
我们可以先拿2b个合成A,然后合成b个奖品,然后只有c可能大于0.然后5个c可以合成一个奖品

ans += b
c -= 3*b//先花2*b个合成b个A,然后合成b个奖品,合计3b个
b = 0
ans += c / 5

不然的的话,先把B,C的数量弄的相等,然后2个b两个c可以合成一个奖品

temp = (c-b)/2;//先合成temp个奖品
ans += temp;
c = c - temp * 3;
b -= temp;
ans += (b+c) / 4;

全部代码

int numberofprize(int a,int b,int c)
{
    if(a > b)
        swap(a,b);
    if(b > c)
    {
        swap(b,c);
    }
    if(a > b)
    {
        swap(a,b);
    }
    int ans = 0;
    ans = a;
    b -= a;
    c -= a;
    if(c - 2*b >= b)//修改
    {
        c -= 3*b;
        ans += b;
        ans += (c/5);
    }
    else{
        long long temp = (c-b)/2;
        ans += temp;
        c = c - temp * 3;//修改
        b -= temp;//修改
        ans += (b+c) / 4;
    }
    return ans;

}

第二题

题意:告诉你有n个房子并且告诉了房子的中心和长度,是按序排列的。问我们建造一栋长度为t的且挨着其他房子的方案有多少种。
思路:我们可以知道房子是有序排列的,不难发现,方案至少是2种,即第一个房子的西边和最后一个房子的东边,
那么我们只需要判断一下房子与房子之间能否建房子,如果房子之间的长度比t长那么就有2种方案,如果和t一样
长就有一种方案,否则就没有。我们遍历每个房子之间的距离,特别的两个房子有奇数的情况下特殊考虑一下就可以了。

int getHouse(int t,int *a,int xalen)
{
    int ans=2;
    for (int i = 2; i <xalen ; i+=2) {
           int r=a[i-2]+a[i-1]/2;
           int l=a[i]-a[i+1]/2;
           int k;
           if(a[i-1]%2!=0&&a[i+1]%2!=0)
           {
                  k=l-r-1;
               if(k==t)
                   ans++;
               if(k>t)
                   ans+=2;
           }
           else if(a[i-1]%2==0&&a[i+1]%2==0)
           {
               k=l-r;
               if(k==t)
                   ans++;
               if(k>t)
                   ans+=2;
           } else{
               if(l-r>=t)
                   ans+=2;
           }
    }
    return ans;
}

第三题

思路:不难想到枚举所有情况,枚举所有情况不难想到搜索,搜索不难想到用DP来优化。 我们讲细一点,怎么从搜索联系到DP。
如果用搜索,那么怎么来表示呢。可以用DFS(pos,val)来表示到了第pos个位置,然后最后一位是val。
那么

   void dfs(int pos,int val)
   {
             if(pos==L+1)  ans++;
             for(int i=0;i<=9;i++){
                     dfs(pos+1,(i+val)/2);
                     if((i+val)&1) dfs(pos+1,(i+val)/2+1);
              }
   }

我们来分析,(1)他那些地方重复了,(2)怎么修改为DP。
(1) pos+1不变,但是val却有很多个可以变为同一个,他们可以合并,然后再去DFS。
(2) 所以可以变为DP,DP就是一种解决重复问题的算法,很明显我们的DFS满足DP的条件:由于pos单调,无后效性。当然还有其他性质,可以自己检验。 DFS转为DP,首先我们得观察DFS,DFS有二维,DP也可以用二维,用dp[pos][val]表示已经表示了pos位,最后一位是val的方案。
不难得到:

            for(j=0到9)
            int x=j+c[i]-'0';
            dp[i][x/2]+=dp[i-1][j];
            ...x为奇数再+

到了现在,还剩下最后一个问题,和原来的数字重复,我们直选要判定是否可以满足题意造一个出来即可,如果可以,答案-1即可。
判定方法:如果从前往后,如果都满足:前一个数字+(0-9)的一半可以变为后一个数字,则满足。

class Solution{
public:
    long long getPassWordCount(string password){
        int L=password.length(),F=1;
        long long dp[110][10];
        memset(dp,0,sizeof(dp));
        for(int i=0;i<=9;i++) dp[0][i]=1;
        for(int i=1;i<L;i++){
           int w=password[i-1]-'0';
           int v=password[i]-'0';
           if(!(w/2<=v&&((w+9)/2>=v))) F=0;
           for(int j=0;j<=9;j++){
             int x=j+password[i]-'0';
             if(x&1){
                 dp[i][x/2]+=dp[i-1][j];
                 dp[i][x/2+1]+=dp[i-1][j];
             }
             else {
                 dp[i][x/2]+=dp[i-1][j];
             }
           }
        }
        long long  ans=0;
        for(int i=0;i<=9;i++) ans+=dp[L-1][i];
        if(F) ans--;
        return ans;
    }
};

猜你喜欢

转载自blog.csdn.net/nimphy/article/details/108424445
9-5