壓縮dp之noip提高組2005 過河

2021-07-06 04:21:44 字數 1476 閱讀 2572

這題拿到手,很容易想到這樣的乙個dp方程:

f(i) = minof

其中f(i)表示調到i位置最少需要的石子,a[i]表示i位置是否有石子,1表示有,0表示沒有。

但是這題的l範圍達到10^9,如果直接採用上面的dp方程只能拿到30分。

如何改進呢?我們很快注意到石子個數m最大不差過100,那麼顯然m個石子分布在很大的l上,  必然會存在相鄰的石子距離非常大,那麼f(i)會出現在較長的區間內值是一定的!

也就是說,這段很長的距離的f(i)值沒必要繼續乙個個就算,因為這部分的f(i)和前面部分的f(i)是一樣的,換句話說,其對答案沒有貢獻,只是起到乙個「橋梁」、「傳遞」的作用,但是對我們來說,我們完全可以忽略這部分,直接跳到下乙個石子!顯然,如此一來,時間必然過得去。

那麼忽略的部分是多少呢?換句話說,相鄰石子距離壓縮多少而不影響結果呢?當然我們希望越小越好。

那麼我們只要知道多長距離以後,f(i)的值達到穩定。

上圖中, x表示石子位置。其實從x+2t+1之後,f(i)開始穩定,所以我們最多隻需要保留2*t的距離!

但是如果這樣提交的話,我的程式只能拿到80分,有兩個case過不去,發現都是s==t的case。

仔細想想,會發現,上面要想出現這種「傳遞"的作用,其實必須是區域性可連續的,那麼單s==t,就會導致所能跳達的點都是離散的,不符合前述的壓縮做法。

所以加特判即可ac。詳細**如下:

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std;

#define inf 0x3f3f3f3f

#define exp 1e-8

#define ll long long

int l,s,t,m;

int main()

sort(a.begin()+1,a.begin()+m+1);

//printf("%d %d\n",a[0],a[1]);

if (s == t)

} printf("%d\n",ans);

return 0;

} vectorstone(25*m);

int j = 0;

for (int i = 1; i <= m; ++i)else

} vectorf(25*m);

f[0] = 0;

int k = j + t;

for (int i = 1; i <= k; ++i)

} f[i] = maxs;

} printf("%d\n",f[k]);

/*for (int i = 0; i <= l+t; ++i)*/

//system("pause");

return 0;

}

NOIP2015提高組 子串 DP

題目描述 有兩個僅包含小寫英文本母的字串 a 和 b。現在要從字串 a 中取出 k 個互不重疊的非空子串,然後把這 k 個子串按照其在字串 a 中出現的順序依次連線起來得到一 個新的字串,請問有多少種方案可以使得這個新串與字串 b 相等?注意 子串取出 的位置不同也認為是不同的方案。簡單dp。狀態表...

NOIP提高組 矩陣

在麥克雷的面前出現了乙個有n m個格仔的矩陣,每個格仔用 或 表示,表示這個格仔可以放東西,則表示這個格仔不能放東西。現在他拿著一條1 2大小的木棒,好奇的他想知道對於一些子矩陣,有多少種放木棒的方案。因為棍子是1 2的,所以很容易就能發現,兩個被分割的塊,除了跨越兩個塊擺放木棍的方案數會對答案有影...

NOIP提高組2005 路徑壓縮 過河

在河上有一座獨木橋,乙隻青蛙想沿著獨木橋從河的一側跳到另一側。在橋上有一些石子,青蛙很討厭踩在這些石子上。由於橋的長度和青蛙一次跳過的距離都是正整數,我們可以把獨木橋上青蛙可能到達的點看成數軸上的一串整點 0,1,l 其中l是橋的長度 座標為0的點表示橋的起點,座標為l的點表示橋的終點。青蛙從橋的起...