2018上學期程式設計實踐考試總結

mMingfunnyTree發表於2018-07-08

這個部落格不再更新,新部落格地址請戳

算是有那麼一點點遺憾的,考砸了,狀態很差,該出的題沒有出。
達成成就:做不到4題就退隊flag秒破。

考試結束後和岑巨說,自己每次到了比較重要的比賽或者考試的時候,總會有點失眠。
希望到區域賽的時候能克服一下吧,精力不足很致命啦。
(然後謝大神補刀:BB這麼多幹嘛,你個菜逼(orzorz

好了下面主要是做題的過程和思路。


流水賬
開場看A,發現見過,但是忘記怎麼寫了,於是跳B;
看B,看不懂,跳C;
C可做,(思路見下面),敲之,TLE,剪枝後ac;
然後再開D,可做,(思路在下面),敲之wa,找不到bug所以棄了;
看E,暫時沒思路;
看F,可做,但是A顯然比F簡單,回過頭做A;
A題過了之後,E題不想開,F題無限wa,B題不會推,歡聲笑語中GG退隊。


A思路:
首先記錄一下字串中,各個字元出現的次數,找到出現次數最多的那個字元出現了多少次,設為cnt吧。
那麼,如果 cnt+p<=n ,該串的答案ans一定是cnt+p
否則,假設多餘了pp個操作,我可以拿這pp個操作隨便換,最後一步換到需要的字元,那麼ans=n
有一個例外,比如 s=“aaa” p=1 ,這個情況下,答案為2,而不是3。
可以歸納為:當串中只有一種字元,並且p=1時,ans=n-1

這題的出題人岑巨已經回家躲著了哈哈哈哈哈。。。


B思路:
首先更新一下最高賠率的值,贏的賠率為w,平局賠率為d,輸的賠率為l,由於一定要贏,三個都得買。
那麼,根據賠率:
買1/w元的贏,如果中了可以得到1元;
買1/d元的平,如果中了可以得到1元;
買1/l元的輸,如果中了可以得到1元;
那麼最後無論如何我都能得到1元。

如果**(1/w+1/d+1/l)<1**,說明我花費小於收穫。
我不管,這題我得甩鍋給沒睡好。


C思路:
根據題意一步一步來便可,看到資料範圍,字串長度等於200,不妨直接列舉一下獲勝一局需要多少積分,
然後列舉一下贏得多少局算獲勝。容易知道需要的積分的範圍可以設為[1,len],那麼一共最多能玩多少局呢?
這裡一開始我寫的[1,len]局,超時了。
剪枝:一局需要i積分,那麼滿足i*j<=len,區間可以修改為[1,len/i]。
至於暴力列舉,就不多說了。


D思路:
柵欄有橫豎兩種,我們可以從輸入中統計一下每個橫向的柵欄能夠阻止多少對豬,每個縱向能夠阻止多少對豬。
那麼,如果這根柵欄有貢獻了,一定要算進去。

如果給的柵欄數足夠了,直接輸出答案。如果給的不夠,那麼直接對貢獻排序,把柵欄建在貢獻高的位置便可。

個人認為CD應該放在AB的位置。難度較之簡單一丟丟吧。


E思路:
因為是有向邊,要從各個點到達x,又要回到各個點去,
不妨從x點正向和反向跑2次dijkstra最短路,貌似要加堆優化
也就是建2個鄰接表,一個表存正向邊的圖,一個表存反向邊的圖,二者最短路相加,
找到最大值便可。


F思路:
動態規劃或者記憶化搜尋都能做。
dp[i][j]表示對[1,i]這個區間,拆分為j段,那麼,
dp[n][m]就代表對區間[1.n]拆分為m段的結果。
如何遞推呢?
首先初始化dp陣列,令所有的dp[i][j]=-inf
(考試的時候我初始化為0了,如果要初始化為0,到時候的邊界就要特別注意了。不如直接初始化-inf)

for(int i=1;i<=n;i++){
    for(int j=1;j<=m;j++){
		for(int k=1;k<i;k++){
		    if(k==i-1)dp[i][j]=max(dp[i][j],dp[k][j-1]+a[i]);
		    else dp[i][j]=max(dp[i][j],dp[k][j-1]+abs(a[i]-a[k+1])*(i-k));
		}
    }
}

dp[k][j-1]表示區間[1,k]劃分j-1段的最大值。
dp[i][j]可以由dp[k][j-1]轉移而來。轉移方程如上。


沒有事後諸葛亮啦,及時總結一下總是有好處的叭。
下次再遇到A題這出題人我會替大家收拾他的(岑巨我說著玩的您別當真…)


經驗:
1.保證好睡眠
2.卡題要開新題,尤其是個人賽沒有人給你debug
3.提升各方面奇淫姿勢


溜了溜了~

相關文章