noip模擬測試33
阿新 • • 發佈:2020-11-19
noip模擬測試33
t1 合併集合
sb題,裸的石子合併,考試沒看見有環,掛成20分
程式碼:
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #define int long long using namespace std; const int maxn = 605; inline int read () { int x = 0, f = 1; char ch = getchar(); for (;!isdigit(ch); ch = getchar()) if (ch == '-') f = -1; for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0'; return x * f; } int n, a[maxn]; int tong[maxn]; int js; int num[maxn][maxn], dp[maxn][maxn]; signed main () { freopen ("merge.in", "r", stdin); freopen ("merge.out", "w", stdout); n = read(); for (register int i = 1; i <= n; i++) { a[i] = read(); } for (register int i = 1; i <= n; i++) { a[i + n] = a[i]; } for (register int i = 1; i <= 2 * n; i++) { for (register int j = i; j <= 2 * n; j++) { memset (tong, 0, sizeof tong); js = 0; for (register int k = i; k <= j; k++) { if (tong[a[k]] == 0) { tong[a[k]]++; js ++; } } num[i][j] = js; } } register int r; for (register int len = 2; len <= n; len++) { for (register int i = 1; i + len - 1 <= 2 * n; i++) { r = i + len - 1; for (register int k = i; k < r; k++) { dp[i][r] = max (dp[i][r], dp[i][k] + dp[k + 1][r] + num[i][k] * num[k + 1][r]); } } } int ans = 0; for (register int i = 1; i < n; i++) { ans = max (ans, dp[i][i + n - 1]); } cout<<ans<<endl; return 0; }
t2 ZYB建圍牆
貪心,顯然儘量建蜂窩形,然後如果有多出來的要開闢新一層就儘量佔用更少的邊,貪心就好了
程式碼:
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> using namespace std; inline int read () { int x = 0, f = 1; char ch = getchar(); for (;!isdigit(ch); ch = getchar()) if (ch == '-') f = -1; for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0'; return x * f; } const int maxn = 20010; int n; int cnt[maxn]; int ans[maxn]; int main () { freopen ("wall.in", "r", stdin), freopen ("wall.out", "w", stdout); n = read(); if (n <= 20) {//自行忽略 if (n == 1) { cout<<6<<endl; } else if (n == 2) { cout<<8<<endl; } else if (n == 3) { cout<<9<<endl; } else if (n == 4) { cout<<10<<endl; } else if (n == 5) { cout<<11<<endl; } else if (n == 6) { cout<<12<<endl; } else if (n == 7) { cout<<12<<endl; } else if (n == 8) { cout<<13<<endl; } else if (n == 9) { cout<<14<<endl; } else if (n == 10) { cout<<14<<endl; } else if (n == 11) { cout<<15<<endl; } else if (n == 12) { cout<<15<<endl; } else if (n == 13) { cout<<16<<endl; } else if (n == 14) { cout<<16<<endl; } else if (n == 15) { cout<<17<<endl; } else if (n == 16) { cout<<17<<endl; } else if (n == 17) { cout<<18<<endl; } else if (n == 18) { cout<<18<<endl; } else if (n == 19) { cout<<18<<endl; } else if (n == 20) { cout<<19<<endl; } return 0; } for (register int i = 2; i <= maxn - 5; i++) { cnt[i] = cnt[i - 1] + 6; } int js = 1; n -= 1; for (register int i = 2; i <= maxn - 5; i++) { if (n >= cnt[i]) { n -= cnt[i]; js = i; } else break; } if (n == 0) { cout<<(6 * js)<<endl; return 0; } if (cnt[js + 1] - n < (js + 1)) { cout<<6 * (js + 1)<<endl; return 0; } else { int cntt = 0; if (n < js) { cntt = 1; } else if (n == js) { cntt = 2; } else if (n == js + 1) { cntt = 2; } else if (n > js + 1) { n -= js + 1; cntt = 3; if (n > js - 1) { n -= js - 1; cntt += n / js; } } cout<<((6 * (js + 1)) - (6 - cntt))<<endl; } return 0; }
t3 ZYB和售貨機
顯然對於每個點而言,儘量用他的兒子中價格最小的點來買他,但是可能會出先單獨的環的情況,此時環上一定有一個點剩下一次買不了,但是這個點可以被次優的兒子來購買,因此列舉環上每個點看看這個點如果少買一次,得到的答案最優是多少
對於鏈來說,都買了就好
程式碼:
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #include <vector> #define int long long using namespace std; const int maxn = 1e5 + 50; inline int read () { int x = 0, f = 1; char ch = getchar(); for (;!isdigit(ch); ch = getchar()) if (ch == '-') f = -1; for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0'; return x * f; } struct Edge { int to, next; } edge[maxn]; int tot, head[maxn]; void addedge (int a, int b) { edge[++tot].to = b; edge[tot].next = head[a]; head[a] = tot; } int n; int f[maxn], cost[maxn], val[maxn], cnt[maxn]; struct Node { int id; int cost, val; friend bool operator < (const Node& A, const Node& B) { return A.cost < B.cost; } }; vector <Node> vec[maxn]; int dfn[maxn], low[maxn], dfn_clock, belong[maxn], scc_cnt, siz[maxn]; int stk[maxn], top; vector <int> v[maxn]; void tarjan (int u) { low[u] = dfn[u] = ++dfn_clock; stk[++top] = u; for (register int i = head[u]; i; i = edge[i].next) { int v = edge[i].to; if (!dfn[v]) { tarjan (v); low[u] = min(low[u], low[v]); } else if (!belong[v]) { low[u] = min (low[u], dfn[v]); } } if (low[u] == dfn[u]) { ++scc_cnt; while (1) { int x = stk[top--]; v[scc_cnt].push_back(x); belong[x] = scc_cnt; siz[scc_cnt]++; if (x == u) break; } } } int rd[maxn]; int from[maxn]; signed main () { freopen ("goods.in", "r", stdin), freopen ("goods.out", "w", stdout); //freopen ("in", "r", stdin); n = read(); for (register int i = 1; i <= n; i++) { f[i] = read(), cost[i] = read(), val[i] = read(), cnt[i] = read(); vec[f[i]].push_back((Node){i, cost[i], val[i]}); } for (register int i = 1; i <= n; i++) { if (vec[i].size() == 0) continue; sort (vec[i].begin(), vec[i].end()); if (vec[i][0].cost < val[i]) { from[i] = vec[i][0].id; addedge (vec[i][0].id, i); rd[i]++; } } for (register int i = 1; i <= n; i++) { if (!dfn[i]) tarjan(i); } int finalans = 0; bool judge = false; for (register int i = 1; i <= scc_cnt; i++) { if (v[i].size() == 1) { if (from[v[i][0]] == 0) continue; finalans += (val[v[i][0]] - cost[from[v[i][0]]]) * cnt[v[i][0]]; } else { int ans = 0, sum = 0; bool judge2 = false; for (register int j = 0; j < v[i].size(); j++) { sum += (val[v[i][j]] - cost[from[v[i][j]]]) * cnt[v[i][j]]; } for (register int j = 0; j < v[i].size(); j++) { int now = v[i][j]; if (vec[now].size() == 1) { ans = max (ans, sum - (val[v[i][j]] - cost[from[v[i][j]]])); } else if (vec[now][1].cost > val[now]) { ans = max (ans, sum - (val[v[i][j]] - cost[from[v[i][j]]])); } else { ans = max (ans, sum - vec[now][1].cost + cost[from[now]]); } } finalans += ans; } } cout<<finalans<<endl; return 0; }
t4 ZYB玩字串
還不會, 咕咕咕