1. 程式人生 > 實用技巧 >【題解】牛客程式設計巔峰賽S1賽季第1場 - 青銅&白銀局

【題解】牛客程式設計巔峰賽S1賽季第1場 - 青銅&白銀局

總結

身敗名裂 一生之恥
  1. 沒寫過函數語言程式設計,十分不習慣
  2. \(\texttt{C}\)題的\(\texttt{vector}\)不會用,像傻子一樣看著螢幕不知道該咋辦
  3. 罰時罰了五次,還都是傻逼錯誤

最後成了一個小小的白銀……我真是太菜了!

題解

A 移動字母

連結

題意

給出一個字串,讓你把這個字串中的小寫字母\(a\)移到字串的最後

思路

眾所周知\(\texttt{string}\)是具有可加性的,所以可以新建一個字串\(t\)儲存新的字串,並用\(cnt\)記錄\(a\)的個數,將\(s\)迴圈一遍如果\(s[i]=='a'\)就累積到計數器\(cnt\)中,否則加入\(t\)串中,然後迴圈一遍將\(cnt\)

\(a\)加到\(t\)串中,最後輸出即可

程式碼

class Solution {
    public:
    string change(string s) {
        // write code here
        int n = s.length();
        int cnt = 0;
        string t;
        for (int i = 0; i < n; i++)
            if (s[i] == 'a') cnt++;
            else t += s[i];
        for (int i = 1; i <= cnt; i++)
            t += 'a';
        return t;
    }
};

B 魔法數字

連結

題意

給出兩個數\(n,m\),有三種操作:

  1. 當前數加\(1\)
  2. 當前數\(-1\)
  3. 當前數平方

\(n\)最少操作多少次可以變成\(m\)

思路

廣搜

用一個\(pair\)型的佇列,第一維是當前數,第二維是所用的步數

根據題目條件設定三個變數分別為加之後的結果、減之後的結果、平方之後的結果,按照常規廣搜思路入佇列,根據廣搜的性質,最先搜到\(m\)的次數就是答案,返回即可

程式碼

class Solution {
	public:
		int solve(int n, int m) {
			queue <pair<int, int> > Q;
			int vis[10001], x, y;
			memset(vis, 0, sizeof(vis));
			Q.push({n, 0}), vis[n] = 1;
			while (Q.size()) {
				x = Q.front().first, y = Q.front().second;
				Q.pop();
				if (x == m) return y;
				//a加之後的結果,b減之後的結果,c平方之後的結果
				int a = x + 1, b = x - 1, c = x * x;
				if (a < 1000 && !vis[a]) Q.push({a, y + 1}), vis[a] = 1;
				if (b >= 0 && !vis[b]) Q.push({b, y + 1}), vis[b] = 1;
				if (c < 1000000 && !vis[c]) Q.push({c, y + 1}), vis[c] = 1;
			}
		}
};

C 牛妹的春遊

連結

題意

給出需要的麵包數\(n\)和飲料數\(m\)

給出\(?\)個揹包,每個揹包中有\(p_1\)個麵包,\(p_2\)瓶飲料,花費為\(p_3\)

求最小花費

思路

二維費用揹包問題

比賽的時候不會用\(\texttt{vector}\)。。。。結束之後發現和陣列沒啥兩樣

在題解裡看到一個大佬說函式引數是可以改名的……於是改成了\(a,b,v\)

其實揹包的數量就是\(v.size()\)

然後就和\(01\)揹包類似了,選或不選這個揹包,優化也一樣

但是其實是可以買多的,可能會出現減出負數的情況,這個時候只要對負數體積取\(0\)即可,表示即使當前需要的飲料/麵包小於袋子中的飲料/麵包數量依然可以購買

最後返回\(f[a][b]\)即可

程式碼

class Solution {
	public:
		int f[2000][2000];
		int minCost(int a, int b, vector<vector<int> >& v) {
			memset(f, 0x3f, sizeof(f));
			f[0][0] = 0;
			for (int i = 0; i < v.size(); i++)
				for (int j = a; j >= 0; j--)
					for (int k = b; k >= 0; k--)
						f[j][k] = min(f[j][k], f[max(j - v[i][0], 0)][max(k - v[i][1], 0)] + v[i][2]);
			return f[a][b];
		}
};