程设2023期末

A.围栏

#include <iostream>
using namespace std;
int main(){
	long long n, ans = 0;cin>>n;
	for(long long i = 1; i <= n; ++i){
        if (n % i) break;
		long long tmp = n % i;
		if (tmp < i) break;
		ans = max(ans, (i + tmp) * 2);
	}cout<<ans<<endl;
	return 0;
}

B.解密

#include <iostream>
#include <cstdio>

using namespace std;

string solve(string a){
	int len = a.length();
	int mid = (len + 1) / 2;
	if (len <= 2) return a;
	string str1(a, 1, mid - 1), str2(a, mid, len - mid), str3(a, 0, 1);
	return solve(str1) + str3 + solve(str2);
}

int main(){
	string a;cin>>a;
	cout<<solve(a)<<endl;
	return 0;
}

String语法

直接把string作为参数在函数中传递,看似浪费时间,实际上复杂度也是\(O(nlogn)\)

C.传送法术

#include <iostream>
#include <cstdio>

using namespace std;

const int inf = 1000000000;
int n;string a;
int f[2000];

int main(){
	cin>>n>>a;int s, t;
	for (int i = 0; i < n; ++i){
		f[i] = inf;
		if (a[i] == 'S') s = i;
		if (a[i] == 'T') t = i;
	}f[s] = 0;
	for (int j = 0; j < n; ++j){
		for(int i = 0; i < n; ++i){
			if (a[i] == '#') continue;
			if (i != 0) f[i] = min(f[i], f[i - 1] + 1);
			if (i != n) f[i] = min(f[i], f[i + 1] + 1);
			f[i] = min(f[i], f[n - i - 1] + 1);
		}
	}
	if(f[t] == inf) cout<<-1;
	else cout<<f[t];
	return 0;
}

用floyd的思想,最多进行n次松弛操作,复杂度\(O(n^2)\)

D.购买优惠券

二分答案,不知道为什么边界总是调不好

#include <iostream>
#include <cstdio>
#define int long long

using namespace std;

int a[200000];
int n, m, sum = 0;

bool solve(int x){
	int cnt = 0, now = 0;
	for (int i = 1; i <= n; ++i){
		if (a[i] > x) return false;
		if (now + a[i] > x) {cnt++; now = 0;}
		now += a[i];
		if (cnt > m) return false;
	}
	if (cnt == m && now > 0) return false;
	return true;
}

signed main(){
	cin>>n>>m;
	for (int i = 1; i <= n; ++i) {
		cin>>a[i];sum += a[i];
	}
	int l = (n + m - 1) / m, r = sum + 1;
	while (l < r){
		int mid = (l + r) / 2;
		if (solve(mid)) r = mid;
		else l = mid + 1;
	}
	cout<<l<<endl;
	return 0;
}

E.建筑修建

经典贪心

#include<iostream>
#include<algorithm>
using namespace std;

int n, m, x[2000], y[2000];
struct building{
	int l,r;
}a[2000];

bool cmp(building x, building y) {return x.r < y.r;}

int main() {
	cin>>n>>m;
	for (int i = 1; i <= n; ++i){
		cin>>x[i]>>y[i];
		a[i].l = x[i]; a[i].r = x[i] + y[i] - 1;
	}
	sort(a + 1, a + n + 1, cmp);
	int now = -1, ans = 0;
	for (int i = 1; i <= n; ++i){
		if (a[i].l > now && a[i].r < m){
			++ans;now = a[i].r;
		}
	}
	cout<<ans<<endl;
    return 0;
}

F.预测赢家

#include <iostream>
#include <vector>
using namespace std;
vector<int> a;

int solve(int l, int r){
	if (r == l) return a[l];
	if (r - l == 1) return max(a[l], a[r]) - min(a[l], a[r]);
	return max(min(solve(l + 2, r) + a[l] - a[l + 1], solve(l + 1, r - 1) + a[l] - a[r]), 
			min(solve(l, r - 2) + a[r] - a[r - 1], solve(l + 1, r - 1) + a[r] - a[l]));
}

int main(){
	int T;cin>>T;while (T--){
		int m;cin>>m;a.clear();
		for (int i = 1; i <= m; ++i) {
			int x;cin>>x;a.push_back(x);
		}
		if (solve(0, m - 1) >= 0) cout<<"true"<<endl;
		else cout<<"false"<<endl;
	}
	return 0;
}

读题!!!又吃了没读懂题就开始写代码的亏,think twice code once

G.海拔

最小生成树(并查集)。

#include <iostream>
#include <map>
#include <algorithm>
using namespace std;

int n, m, h[500][500];
struct edge{
	pair<int, int> s, t;
	int len;
	bool operator < (const edge& temp)const{
		return len < temp.len;
	}
}a[200000];int cnt;
map<pair<int, int>, pair<int, int> > fa;

void add(int sx, int sy, int tx, int ty, int len){
	a[++cnt].len = len;
	a[cnt].s = make_pair(sx, sy);
	a[cnt].t = make_pair(tx, ty);
	fa[a[cnt].s] = a[cnt].s;fa[a[cnt].t] = a[cnt].t;
}

auto fnd(auto x){
	if (fa[x] == x) return x;
	else return fa[x] = fnd(fa[x]);
}

int main(){
	cin>>n>>m;
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= m; ++j){
			cin>>h[i][j];
			if (i > 1) add(i, j, i - 1, j, abs(h[i][j] - h[i - 1][j]));
			if (j > 1) add(i, j, i, j - 1, abs(h[i][j] - h[i][j - 1]));
		}
	sort(a + 1, a + cnt + 1);
	pair<int, int> S = make_pair(1, 1), T = make_pair(n, m);
	for (int i = 1; i <= cnt; ++i){
		auto s = a[i].s, t = a[i].t;
		if (fnd(s) != fnd(t))
			fa[fnd(s)] = fnd(t);
		if (fnd(S) == fnd(T))
			{cout<<a[i].len<<endl;return 0;}
	}
    return 0;
}

I.取数游戏

爆搜

#include <iostream>
#include <vector>
using namespace std;

struct lecture{
	int k, v;
	vector<int> c;
}a[200];
int n, ans;
int vis[20];

bool f(int now){
	for (int i = 0; i < a[now].c.size(); ++i){
		if (vis[a[now].c[i]]) return 0;
	}return 1;
}

void dfs(int now, int nowv){
	if (now > n) return;
	if (f(now)){
		for (int i = 0; i < a[now].c.size(); ++i){
			vis[a[now].c[i]] = 1;
		}
		ans = max(ans, nowv + a[now].v);
		dfs(now + 1, nowv + a[now].v);
		for (int i = 0; i < a[now].c.size(); ++i){
			vis[a[now].c[i]] = 0;
		}
	}
	dfs(now + 1, nowv);
}

int main(){
	cin>>n;
	for (int i = 1; i <= n; ++i){
		cin>>a[i].k>>a[i].v;
		for (int j = 0; j < a[i].k; ++j){
			int x;cin>>x;a[i].c.push_back(x);
		}
	}
	dfs(1, 0);
	cout<<ans<<endl;
	return 0;
}

H.课程安排

仍然是爆搜

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int n, m, a[10][10], ans;
int vis[10][10];

int fx[9] = {0, 0, 0, 1, 1, 1, -1, -1, -1};
int fy[9] = {0, 1, -1, 0, 1, -1, 0, 1, -1};

bool f(int x, int y){
	for(int i = 0; i < 9; ++i)
		if(vis[x + fx[i]][y + fy[i]])
			return 0;
	return 1;
}

void dfs(int x, int y, int now){
	if (x == n && y == m) return;
	if (f(x, y)){
		vis[x][y] = 1;
		ans = max(ans, now + a[x][y]);
		dfs(y == m ? x + 1 : x, y == m ? 1 : y + 1, now + a[x][y]);
		vis[x][y] = 0;
	}
	dfs(y == m ? x + 1 : x, y == m ? 1 : y + 1, now);	
}

int main(){
	int T;cin>>T;while (T--){
		cin>>n>>m;
		for (int i = 1; i <= n; ++i)
			for (int j = 1; j <= m; ++j)
				cin>>a[i][j];
		dfs(1, 1, 0);
		cout<<ans<<endl;
		ans = 0;
	}
}

J.分配工作

搜索剪枝,这种分组类型的搜索还不熟练。

剪枝应该是叫IDA*的思想(?),就是剪掉大于阈值的部分

#include <iostream>
#include <cstdio>

using namespace std;

const int inf = 1000000000;
int ans = inf, cnt;
int t[20], vis[20];

void dfs(int n, int k, int now, int nowmax){
	if (n == 0 && k == 0){
		ans = min(ans, nowmax);
		return;
	}
	for (int i = 1; i < cnt; ++i){
		if (vis[i]) continue;
		vis[i] = 1;
		if (now + t[i] > nowmax && k != 0){
			dfs(n - 1, k - 1, t[i], max(nowmax, t[i]));
		}
		if (n - 1 >= k && now + t[i] < ans){
			dfs(n - 1, k, now + t[i], max(nowmax, now + t[i]));
		}                                                
		vis[i] = 0;   
	}
}

int main(){
	int k;cin>>cnt>>k;
	for (int i = 0; i < cnt; ++i) cin>>t[i];
	dfs(cnt - 1, k - 1, t[0], t[0]);
	cout<<ans<<endl;
	return 0;
}

K.蛇入迷宫

#include <iostream>
#include <vector>
using namespace std;

int n, a[200][200], vis[200][200], ans = 1000000000;

void dfs(int x, int y, int to, int now){
	if(x == n - 1 && y == n - 1 && to == 1){
		ans = min(ans, now);return;
	}
	vis[x][y] = 1;
	if (to == 1){
		if (y + 1 < n && a[x][y + 1] == 0 && vis[x][y + 1] == 0){
			dfs(x, y + 1, 1, now + 1);
		}
		if (x + 1 < n && a[x + 1][y] == 0 && a[x + 1][y - 1] == 0 && vis[x + 1][y - 1] == 0){
			dfs(x + 1, y, 1, now + 1);
			dfs(x + 1, y - 1, 0, now + 1);
		}
	}
	else{
		if (x + 1 < n && a[x + 1][y] == 0 && vis[x + 1][y] == 0){
			dfs(x + 1, y, 0, now + 1);
		}
		if (y + 1 < n && a[x][y + 1] == 0 && a[x - 1][y + 1] == 0 && vis[x - 1][y + 1] == 0){
			dfs(x, y + 1, 0, now + 1);
			dfs(x - 1, y + 1, 1, now + 1);
		}
	}
	vis[x][y] = 0;
}

int main(){
	cin>>n;
	for (int i = 0; i < n; ++i)
		for (int j = 0; j < n; ++j)
			cin>>a[i][j];
	if (a[n - 1][n - 1] || a[n - 1][n - 2]) {cout<<-1<<endl;return 0;}
	dfs(0, 1, 1, 0);//pos of head is (0, 1), its body is level
	if (ans != 1000000000) cout<<ans<<endl;
	else cout<<-1<<endl;
	return 0;
}

L.最长奇异子序列

因为我们更新状态的时候只会考虑上一个数而不会考虑之前的数,所以设 f[i][j] 表示前i个数形成的最长奇异子序列且最后一个数的第 j 位是 1 。那么 f[i][j] = max{f[i - 1][k]} + a[i][j], k 是 a[i] 为 1 的数位。

滚动数组优化到一维。(lyt实在太强了

#include <iostream>
#include <cstdio>

using namespace std;

int a[200000], f[100000];

int g(int x){
	int ret = 0;
	for (int j = 1; j <= 32; ++j){
		if (x % 2) ret = max(ret, f[j]);
	}return ret + 1;
}

int main(){
	int T;cin>>T;while (T--){
		int n, ans = 0;cin>>n;
		for (int i = 1; i <= n; ++i){
			cin>>a[i];
			int num = g(a[i]);
			for (int j = 1; j <= 32; ++j){
				if (a[i] % 2) f[j] = num;
				a[i] /= 2;
				ans = max(ans, f[j]);
			}
		}
		cout<<ans<<endl;
	}return 0;
}
posted @ 2024-05-08 09:19  hcx1999  阅读(16)  评论(0编辑  收藏  举报