1. 程式人生 > 其它 >4.10考試(過程)

4.10考試(過程)

上來看到problem1,想到了之前比賽做過的“遊戲”問題,這兩個題何其相似。

第一時間想考慮貪心,推了一會兒,發現這個題的不適用貪心策略(即使可能有這樣的策略,判斷也過於複雜)

不貪了,搜尋

寫到一半,想了想一些特殊判斷剪枝,n與k均為正數,k小於n的情況下方法沒得選,只能不斷-1,於是把它加在前面了:

if(k<n) printf("%d\n",n-k),exit(0);

寫搜尋的時候也卡了一會,因為一開始想用一個變數ans記錄,不現實啊!應該用陣列記錄到達某個點的步數。

problem2:單調序列,先找了找幾個特點:

第一,不上升和不下降兩個都要考慮;

第二,目標未知;

第三,要求最小改變數,而不是最小改變次數。

由第三點就知道肯定要動態規劃來做,但是目標未知!

所以思考了一下,最優策略下改變結果一定都是原序列有的數

比如1 3 2 4 5 3 9 -->1 3 3 4 5 5 9,其中設b[]={1,2,3,4,5,9}作為目標陣列。

然後就要考慮怎麼dp了,這段最費時間,不過好在能夠解決第一點(不上升和不下降,改變dp順序即可)

然後開始寫,中間還是要注意初始化。

int dp(){
    memset(f,0x5f,sizeof(f));
    memset(f[0],0,sizeof(f[0]));
    FOR(i,1,n){
        FOR(j,0,m){
            f[i][j] 
= min(f[i][j-1],f[i-1][j]+abs(a[i]-b[j])); } } int ans = f[n][m]; //正反搜兩次 memset(f,0x5f,sizeof(f)); FOR(i,1,n){ ROF(j,m,0){ f[i][j] = min(f[i][j-1],f[i-1][j]+abs(a[i]-b[j])); } } ans = min(ans,f[n][m]); return ans; }

problem3,一眼看出來是樹狀陣列/線段樹問題。

(大樣例的億點問題好像對我沒影響,能正常輸出不知為什麼)

兩個操作是區間修改+區間查詢?(這個超出我能力範圍,但是勉強寫了個單點查詢+迴圈,可能超時)

先寫了前面的樹狀陣列一些基本函式(忘得差不多了)

然後才想起來要用b[i]=a[i]-a[i-1]來構成陣列。

判斷大於c的部分,卡了40分鐘左右,後面就寫暴力提交了。