AtCoder Beginner Contest 204 補題記錄
阿新 • • 發佈:2021-11-08
寄了,vp一場只寫出了兩道題,我是彩筆
C - Tour
題目大意:給定n個點m條單向邊,求總共有多少個點對能夠滿足(i,j)從i到j
解題思路:在寫題目的時候想到用環去寫,只要找到環的數量就可以計算,但是苦於找不到所有環,由於給的資料範圍非常小(只有2000),那麼在n ^ 2的時間複雜度的演算法都能夠被接受,那麼我們遍歷一遍全圖是O(n)的時間,n個點都遍歷一遍就是n ^ 2,那麼我們就可以通過暴力直接去寫
反思:考慮到時間複雜度,沒考慮到暴力做法,想法太過侷限
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 2e3 + 10; vector<vector<int> > G; int vis[maxn]; int T,n,m; int u,v; ll ans = 0; void BFS(int s) { queue<int> q; q.push(s); vis[s] = 1; while(!q.empty()) { int x = q.front(); q.pop(); for(int h:G[x]) { if(vis[h] == 0) { vis[h] = 1; q.push(h); } } } } void DFS(int s) { if(vis[s]) return; vis[s] = 1; for(auto h:G[s]) { if(vis[h] == 0) { DFS(h); } } return; } void solve() { scanf("%d %d",&n,&m); G.resize(maxn); for(int i = 1;i <= m;++i) { scanf("%d %d",&u,&v); G[u].emplace_back(v); } for(int i = 1;i <= n;++i) { for(int j = 1;j <= n;++j) vis[j] = 0; DFS(i); for(int j = 1;j <= n;++j) { if(vis[j]) ans++; } } printf("%lld\n",ans); } int main() { T = 1; while(T--) { solve(); } return 0; }
D - Cooking
解題思路:給定n個物品需要烹飪,我們有2個鍋,求我們需要烹飪最短時間
解題思路:在做題過程中,想到其實物品如何擺放是對最終結果沒有影響的,無論最終如何都只有A鍋和B鍋加起來是全部的時間,那麼我們假設A鍋時間比較大,那麼對於A鍋來說,我們要儘可能找到A的大於所有烹飪時間一半的最小值。但是如何去找呢?
想法一:二分,我們可以通過二分去列舉時間,但是如何去線性的表示並且修改相對應的遞增遞減呢?
因此二分的想法被我們給否決了,但是對於任意一個時刻對於任意一個物品,我們如果需要把物品放入,這個時間是取決於之前的時間的,分析時間複雜度我們可以發現ai的值並不是很大,因此我們可以想到如果有一個東西是儲存之前i - 1個物品所需要的時間,那麼對於第i 個時間來說,我們我們就可以進行計算了
那麼對於A鍋來說,設出動態規劃轉移方程式dp[i][j],i表示第i個物品,j表示可能需要的時間,那麼對於這一時刻如果我們這裡有東西的,我們可以選擇把物品放在b鍋,則dp[i + 1][j] = 1;我們也可以選擇把東西放回A鍋,那麼可以得出dp[i + 1][j + a[i]] = 1
需要注意的是我們的邊界點是dp[0][0] = 1,邊界迴圈是從0 - > n - 1
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e5 + 10; bool dp[110][maxn]; int T,n,m; int a[110]; int sum = 0; void solve() { scanf("%d",&n); for(int i = 1;i <= n;++i) { scanf("%d",&a[i]); sum += a[i]; } dp[0][0] = 1; for(int i = 0;i < n;++i) { for(int j = 0;j <= sum;++j) { if(dp[i][j]) { dp[i + 1][j] = 1; dp[i + 1][j + a[i + 1]] = 1; } } } for(int i = (sum + 1) / 2;i <= sum;++i) { if(dp[n][i]) { printf("%d\n",i); break; } } } int main() { solve(); return 0; }