首页 > 技术文章 > noip模拟测试33

hzoi-liujiahui 2020-11-19 17:12 原文

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玩字符串

还不会, 咕咕咕

推荐阅读