題目鏈結
題意:乙個二維平面,長為\(n\),寬為\(m\),其中有\(k\)個管道,小鳥從最左邊任意整數高度位置出發,到達遊戲介面最右邊時,遊戲完成。
小鳥每個單位時間沿著\(x\)軸向右移動乙個單位距離,小鳥在從\(i\)移動到\(i +1\)時,玩家可以選擇是否點選螢幕(可以點選多次),若不點選,小鳥將下降\(y_i\)單位距離,若點選\(j\)次,小鳥的上公升距離為\(j\times x_i\)。
當小鳥碰到管壁或縱座標等於\(0\)時,遊戲結束。小鳥的高度可以不停上公升,但最高不超過\(m\),(可以到達\(m\),遊戲不會結束)。
管道:並不是每個橫座標都對應乙個管道,管道有乙個上邊沿高度和乙個下邊沿高度。
藍色直線表示小鳥的飛行軌跡,紅色直線表示管道。
求是否可以完成遊戲,如果可以,求最小點選次數,如果不可以,求最多可以通過多少個管道縫隙。
資料範圍:
\(5\le n\le10000,5\le m\le1000\)
\(70\,\,points\)
這個\(dp\)方程除了跳到頂比較難處理以外,還是很容易想到的,
但相對的,時間複雜度也很大,\(o(nm^2)\)
for(int i = 1; i <= n; i++)
if(j == m)}}
}
\(100 \,\,points\)
考慮如何把時間複雜度優化到\(o(nm)\),
首先列舉橫座標和縱座標是難以優化的,
考慮\(x = 3\)的情況(眾所周知,找規律要從\(3\)開始找)
\(dp[3,10] = min(dp[2,7] + 1,dp[2,4]+2,dp[2,1] +3)\)
\(dp[3,7] = min(dp[2,4] + 1,dp[2,1] + 2)\)
\(dp[3,4]=min(dp[2,1] + 1)\)
由以上的規律,我們很容易得出以下的乙個式子:
\(dp[i][j] = min(dp[i - 1][j - x[i - 1]] + 1, dp[i][j - x[i - 1]] + 1)\)
好吧,其實不用這麼麻煩,可以用從上一次轉移必須裝物品的完全揹包進行理解
for(int i = 1; i <= n; i++)}}
}
#include #include #include using namespace std;
#define maxn 10100
int n, m, k;
int x[maxn], y[maxn], l[maxn], h[maxn];
int dp[maxn][1010];
int main()
l[n] = 0; h[n] = m + 1;
for(int i = 1; i <= k; i++)
for(int i = 1; i <= m; i++) dp[0][i] = 0;
for(int i = 0; i <= n; i++)}}
for(int j = 1; j <= m - y[i - 1]; j++)
}int cnt = 0, ans = 0;
for(int i = 0; i <= n; i++)
else ans = min(ans, dp[i][j]);}}
}int tot = 0;
if(cnt != n)
if(cnt == n) printf("1\n"); else printf("0\n");
if(cnt == n) printf("%d\n", ans); else printf("%d\n", tot);
return 0;
}
NOIP2014 飛揚的小鳥
題目 分析 乙個揹包問題。i,j 是跳上來的情況時 可以由 i,j k 得到,則問題得到解決。注意 f陣列要先進行上公升操作,再進行下降操作,否則 i,j k 有可能是下降得到的,從而得到錯解 吸取我的教訓吧,調了好長時間 include include using namespace std co...
NOIP2014飛揚的小鳥
天哪細節問題調了乙個鐘,手速不夠快思路不夠清晰寫了乙個鐘,感覺一道第三題就要花掉我2個鐘那我比賽的時候腫麼辦qaq 說下這道題,首先純暴力,70分到手,然後我們把01揹包的轉移變成有上界的完全揹包,還有一些特殊情況特殊轉移,還是比較好看的,去年比賽不知是電腦問題還是什麼一直沒輸出,蠢到家了然後這題爆...
NOIP2014 飛揚的小鳥
傳送門 為了簡化問題,我們對遊戲規則進行了簡化和改編 1.遊戲介面是乙個長為n,高 為m的二維平面,其中有k個管道 忽略管道的寬度 2.小鳥始終在遊戲介面內移動。小鳥從遊戲介面最左邊任意整數高度位置出發,到達遊戲介面最右邊時,遊戲完成。3.小鳥每個單位時間沿橫座標方向右移的距離為1,豎直移動的距離由...