看到\(「l 的最小值」\),很容易想到二分答案,那麼這道題的關鍵就是如何快速地檢驗
首先,如果已經規定了操作順序,我們可以\(o(n)\)貪心求解
但是要列舉順序的話複雜度是階乘級別的,顯然布星
於是考慮\(dp\),我一開始的\(dp\)狀態:\(dp[i][j]\)表示乾掉前\(i\)個\(fa\)壇,用\(j\)次紅光時的最少用多少次綠光
發現轉移有些麻煩,又因為時間不大夠了,我就隨機操作順序+貪心\(100\)次了(騙到\(60\)分)
題解的做法:
\(dp[i][j]表示用i次\color和j次\color最多摧毀從1開始多少個連續的法壇\)
轉移就是
\[dp[i][j]=p[dp[i-1][j]+1]+q[dp[i][j-1]+1]
\]其中\(p[k]\)表示從第\(k\)個法壇開始向右\(l\)長度內有多少法壇,\(q[k]\)表示從第\(k\)個法壇開始向右\(2l\)長度內有多少法壇,都可以在\(dp\)前預處理出來
\(60\)分隨機演算法:
#include#include#include#include#include#includeusing namespace std;
const int n=2010;
int n,r,g,a[n];
inline bool check(int l)
else if(tot2!=g)
else break;
} if(dr>a[n]) return 1;
} return 0;
}int main()
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
sort(a+1,a+1+n);
int l=1,r=1000000000;
while(l>1;
if(check(mid)) r=mid;
else l=mid+1;
} printf("%d\n",l);
fclose(stdin); fclose(stdout);
return 0;
}
\(100\)分**
#include#include#include#includeusing namespace std;
#define n 2010
#define reset(a) memset(a,0,sizeof(a))
int n,r,g,a[n],dp[n][n];
int p[n],q[n];
bool check(int l)
p[n+1]=q[n+1]=n;
for(int i=0;i<=r;i++)
for(int j=0;j<=g;j++)
return dp[r][g]==n;
}int main()
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+1+n);
int l=1,r=1e9;
while(l>1;
if(check(mid)) r=mid;
else l=mid+1;
} printf("%d\n",l);
fclose(stdin); fclose(stdout);
return 0;
}
模擬 神奇的樹
time limit 1000ms memory limit 65536k sdut有一顆神奇的蘋果樹。假如某天早上這樹上有x個蘋果,那麼這樹這一天會再結出x個蘋果來,也就是說到了晚上會有2 x個蘋果,到了深夜,會有專人人來摘蘋果,而摘蘋果的人總會使蘋果數剩下當前數量對m的餘數,也就是說假如當前數量...
校內模擬 鎖
沒有標籤是因為我真的不知道這算什麼型別 這題我說不來大意你們還是看題面描述吧 小z住的房子一共有n個人,他們每人有乙個重要度。房子的門上可以裝若干把鎖。假設共有k把鎖,命名為1到k。每把鎖有一種對應的鑰匙,也用1到k表示。鑰匙可以複製若干份並發給任意多個居民。每個人都可以持有若干鑰匙,可以不持有鑰匙...
校內模擬 assignment(DP)
題面見校內oj4693 考慮預處理f k i j f k i j f k i j 表示最長的一段不超過k kk的時候,將長度為i ii的序列分為j jj段的方案數。在k kk相同的狀態之間轉移,顯然有f i j f i 1 j f i 1 j 1 f i k 1 j 1 f i j f i 1 j ...