Nowcoder Girl 2017題目集合詳解

carson0408發表於2018-03-15

        這是對牛客網舉辦的Nowcoder Girl的程式設計比賽的題目做一個題解。

1.勇氣獲得機

這題主要是為了判斷奇偶性,一種逆序的思維,根據倒序的方法求出結果翻轉之後便是正確答案。

程式碼如下:

#-*-coding:utf-8-*-
n=int(raw_input())
s=''
while(n>0):
    if(n%2==0):
        s+='G'
        n=(n-2)/2
    else:
        s+='N'
        n=(n-1)/2
print s[::-1]

2.排列

本題主要的題意就是使i位置上的數不等於i,因此對陣列data採用遍歷的方法,當data[i]=i+1時需要對i上面的數字相鄰位置進行交換,理論上有幾個data[i]=i+1的情況就需要交換幾次,但是這裡有種特殊情況,就是當data[i]=i+1並且滿足data[i+1]=i+2時,雖然有兩個值滿足要求,但是由於是相鄰的只需要交換一次即可。需要對這種情況進行討論。即用i(i<n)表示陣列的下標遍歷陣列,當沒有相鄰數字滿足的時候,就每出現一次data[i]=i+1,將結果加1,同時i+=1;如果出現相鄰數字滿足時,結果加1,同時i+=2;依次遍歷,直到遍歷完陣列。
#-*-coding:utf-8-*-
n=int(raw_input())
data=map(int,raw_input().split())
i=0
ans=0
while(i<n):
    if(data[i]==i+1):
        if(i+1<n and data[i+1]==i+2):
            i+=2
            ans+=1
        else:
            i+=1
            ans+=1
    else:
        i+=1
print ans

3.叫車

    這題的思路比較明確就是先對擁有的硬幣進行排序,因為需要的硬幣個數越多越好,所以先從小到大進行加,但是當和大於s便停止加;又因為題目要求不能拿掉任意一個硬幣還大於s;所以此時還需要遍歷一遍已經加過的硬幣,為了保證數量是最多的,應該從大到小遍歷,避免減去一個稍微大的可以滿足題目最終要求,但如果從小到大減則需要減大於1個小的,那麼就使得結果不是最優解,因此應該從大到小遍歷,判斷拿掉當前硬幣,是否還大於s,如果是則減去當前硬幣,否則繼續往前遍歷。

# -*-coding:utf-8 -*-
n,s=map(int,raw_input().split())
coin=map(int,raw_input().split())
coin.sort()
sums=0
k=0
ans=0
while(k<n and sums<s):
    sums+=coin[k]
    k+=1
    ans+=1
for i in range(k,0,-1):
    if(sums-coin[i-1]>=s):
        sums-=coin[i-1]
        ans-=1
print ans
#求和應該從小到大加,然後減應該從大到小減

4.勇敢的妞妞

        因為每一種裝備都有五個屬性,所以有一種情況很明確,就是當選取的裝備件數大於等於5件的時候,只需要將每種屬性的最大值相加即可。於是只需要討論k<5的情況:當k=1只需要遍歷求每種裝備的屬性和,取最大值即可;當k=2時,只需要使用i,j變數來控制任意兩個裝備,然後只需要將兩者的每個屬性的較大值相加即可,求出具有最大值的兩兩組合;當k=3,則利用i,j,h來控制三種裝備,思路與k=2時差不多;重點是k=4,如果還用之前的思路,則必然會超時,這時候換種思路,不再控制裝備,而是控制屬性,因為屬性只有五種,所以對時間影響不大,總的屬性有五種,這時候需要選擇四個裝備,如果是五個裝備,那麼只需求每種屬性的最大值即可,那麼四個,則需要將其中的兩個屬性繫結在一起,另外三個則是求最大值,這樣才能保證得到的是最大值,那麼繫結的如何求呢?即遍歷五種屬性,外迴圈控制一種屬性,內迴圈控制與之繫結在一起的屬性,然後通過最內迴圈來控制裝備,這樣可以得到那種裝備的那兩種屬性和是最大的,然後最內迴圈還需要加上剩下三種屬性的最大值,並與結果比較大小,取大值。

首先是Python程式碼,該程式碼只能AC90%。

#-*-coding:utf-8-*-
def solve(n,w,s):
    max_num=[0 for i in range(5)]
    for i in range(n):
        for j in range(5):
            max_num[j]=max(s[i][j],max_num[j])
    res=0
    if(w==1):
        for i in range(n):
            temp=0
            for j in range(5):
                temp+=s[i][j]
            res=max(res,temp)
    elif(w==2):
        for i in range(n):

            for j in range(i+1,n):
                temp = 0
                for k in range(5):
                    temp+=max(s[i][k],s[j][k])
                res=max(res,temp)
    elif(w==3):
        for i in range(n):
            for j in range(i+1,n):
                for k in range(j+1,n):
                    temp=0
                    for h in range(5):
                        temp+=max(s[i][h],s[j][h],s[k][h])
                    res=max(temp,res)
    elif(w==4):#有一個裝備肯定有兩項技能和比較高,貪心
        for i in range(5):
            for j in range(i+1,5):
                temp=0
                for k in range(n):
                    temp=max(temp,s[k][i]+s[k][j])
                for h in range(5):
                    if(k&i==0 and k&j==0):
                        temp+=max_num[h]
                res=max(temp,res)
    else:
        for i in range(5):
            res+=max_num[i]
    return res
if __name__ == '__main__':
    n,k=map(int,raw_input().split())
    s=[]
    for i in range(n):
        w=map(int,raw_input().split())
        s.append(w)
    print solve(n,k,s)

然後根據以上同樣的思路寫的Java程式碼,AC了。

import java.util.*;;

public class Main {
	public static int solve(int n,int k,int[][] s)
	{
		int res=0;
		int[] max_num=new int[5];
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<5;j++)
				max_num[j]=Math.max(s[i][j],max_num[j]);
		}
		if(k==1)
		{
			for(int i=0;i<n;i++)
			{
				int temp=0;
				for(int j=0;j<5;j++)
				{
					temp+=s[i][j];
				}
				res=Math.max(temp, res);
			}
		}
		else if(k==2)
		{
			for(int i=0;i<n;i++)
			{
				for(int j=i+1;j<n;j++)
				{
					int temp=0;
					for(int h=0;h<5;h++)
					{
						temp+=Math.max(s[i][h], s[j][h]);
					}
					res=Math.max(temp, res);
				}
			}
		}
		else if(k==3)
		{
			for(int i=0;i<n;i++)
			{
				for(int j=i+1;j<n;j++)
				{
					for(int e=j+1;e<n;e++)
					{
						int temp=0;
						for(int h=0;h<5;h++)
						{
							temp+=Math.max(s[i][h], Math.max(s[j][h], s[e][h]));
						}
						res=Math.max(temp, res);
					}
				
				}
			}
		}
		else if(k==4)
		{
			for(int i=0;i<5;i++)
			{
				for(int j=i+1;j<5;j++)
				{
					int temp=0;
					for(int e=0;e<n;e++)
					{
						temp=Math.max(temp, s[e][i]+s[e][j]);
					}
					for(int h=0;h<5;h++)
					{
						if(h!=i && h!=j)
							temp+=max_num[h];
					}
					res=Math.max(res, temp);
				}
			}
		}
		else
		{
			for(int i=0;i<5;i++)
			{
				res+=max_num[i];
			}
		}
		return res;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int k=sc.nextInt();
		int[][] s=new int[n][5];
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<5;j++)
			{
				s[i][j]=sc.nextInt();
			}
			
		}
		System.out.println(solve(n,k,s));

	}

}

5.平方數

        本題只需要將輸入的開平方取整,然後再平方即可:

n=int(raw_input())
t=int(n**0.5)
print t*t

6.美麗的項鍊

        本題是一個動態規劃的題,這個題目就類似於湊錢的題目,只不過相當於給每種錢都新增了個數,而不是單純的一個或0個;dp[i][j]表示前i種水晶寶珠能湊成j顆的方法數,當前i的寶珠顆數為li~ri,所以那麼為了湊齊j顆,需要保證前i-1種寶珠需要湊齊多少顆(利用j與li、ri進行簡單計算求得),求得一個範圍都可以,那麼只需要加上前i-1寶珠所有能滿足需求的方案數。程式碼如下:

#-*-coding:utf-8-*-
l=[]
r=[]
n,m=map(int,raw_input().split())
for i in range(n):
    li,ri=map(int,raw_input().split())
    l.append(li)
    r.append(ri)
ways=[[0 for i in range(m+1)] for j in range(n)]
for i in range(l[0],r[0]+1):
    ways[0][i]=1
for i in range(1,n):
    for j in range(m+1):
        left=max(0,j-r[i])
        right=max(0,j-l[i])#當前珠寶種類i的個數有li~ri個,所以前i種珠寶要湊成j個珠寶,則需要使得前i-1種湊成的珠寶數需要在left~right之間,
                            # 那麼第i種才能夠補上。
        for k in range(left,right+1):
            ways[i][j]+=ways[i-1][k]  #ways[i][j]表示i種珠寶湊成j個珠寶的方法數,way[i-1][k]為前i-1種珠寶湊成k個的方法數

print ways[n-1][m]

相關文章