pezhzh的快乐寒假作业[2024/1/16]

文章讲述了作者在编程竞赛中解决一系列C++题目,涉及递归、动态规划、BFS和DFS算法,以及如何通过优化剪枝技巧提高代码效率,最终实现AC或减少错误的状态。
摘要由CSDN通过智能技术生成

 A - kkksc03考前临时抱佛脚

第一次:

才20个数我要穷举!

#include<bits/stdc++.h>
using namespace std;
int res, mi, mii;
int s[5], q[5], a[5][30];
void sear(int n, int m){
	if(mii + a[n][m] > q[n] / 2){
		if(mii > mi) mi = mii;
		return;
	}mii += a[n][m];
	for(int i = m + 1; i < s[n]; i ++){
		sear(n, i);
	}if(mii > mi) mi = mii;
}
int main(){
	for(int i = 0; i < 4; i ++) cin >> s[i];
	for(int i = 0; i < 4; i ++){
		for(int t = 0; t < s[i]; t ++){
			cin >> a[i][t];
			q[i] += a[i][t];
		}//找出小于等于q[i]/2的最大的组合
		mi = 0;
		for(int t = 0; t < s[i]; t ++) {
			mii = 0;
			sear(i, t);
		}
		res += q[i] - mi;
	}cout << res;
} 

40分剩下WA;

忘记加过的数要删除了:

#include<bits/stdc++.h>
using namespace std;
int res, mi, mii;
int s[5], q[5], a[5][30];
void sear(int n, int m){
	if(mii + a[n][m] > q[n] / 2){
		if(mii > mi) mi = mii;
		return;
	}mii += a[n][m];
	for(int i = m + 1; i < s[n]; i ++){
		sear(n, i);
	}if(mii > mi) mi = mii;
	mii -= a[n][m];//sble
}
int main(){
	for(int i = 0; i < 4; i ++) cin >> s[i];
	for(int i = 0; i < 4; i ++){
		for(int t = 0; t < s[i]; t ++){
			cin >> a[i][t];
			q[i] += a[i][t];
		}//找出小于等于q[i]/2的最大的组合
		sort(a[i], a[i] + s[i]);
		mi = 0;
		for(int t = 0; t < s[i]; t ++) {
			mii = 0;
			sear(i, t);
		}res += q[i] - mi;
	}cout << res;
} 

AC;

B - 奇怪的电梯

第一次的程序:

#include<bits/stdc++.h>
using namespace std;
const int N = 300;
vector<int> v[N];
int n, st, ed, k, mk = -1;
int a[N];

void dfs(int num){
    if(num == ed){
        if(k < mk || mk == -1) mk = k;
        return;
    }
    k ++;
    a[num] = 1;
    for(int i = 0; i < v[num].size(); i ++){
        if(!a[v[num][i]]) dfs(v[num][i]);
    }k --;
    a[num] = 0;
}
int main(){
    cin >> n >> st >> ed;
    st --, ed --;
    for(int x, i = 0; i < n; i ++){
        scanf("%d", &x);
        if(i + x < n) v[i].push_back(i + x);
        if(i - x >= 0) v[i].push_back(i - x);
    }dfs(st);
    cout << mk;
}

成功获得52分+8个TLE;

第二次的程序:

加入了当按钮次数超过最小次数就剪枝的判断; 

if(k >= mk && mk != -1) return;

成功获得64分+6个TLE;

第三次的程序:

放弃dfs改用bfs;

#include<bits/stdc++.h>
using namespace std;
const int N = 300;
vector<int> v[N];
queue<int> q;
int n, st, ed, k = -1, res, save;
int a[N];

int main(){
	cin >> n >> st >> ed;
	st --, ed --;
	for(int x, i = 0; i < n; i ++){
		scanf("%d", &x);
		if(i + x < n) v[i].push_back(i + x);
		if(i - x >= 0) v[i].push_back(i - x);
	}
	save = st, res = -1;
	q.push(st);
	while(!q.empty()){
		res = q.front();
		q.pop();
		a[res] = 1;
		for(int i = 0; i < v[res].size(); i ++) if(!a[v[res][i]]) {
			q.push(v[res][i]);
			a[v[res][i]] = 1;
		}
		if(res == save) k ++, save = q.back();
		if(ed == res){
			cout << k;
			return 0;
		}
	}
	cout << "-1";
}

88分+2个WA;

save用的有问题,导致k在特殊情况下少1;

第四次的程序:

#include<bits/stdc++.h>
using namespace std;
const int N = 300;
vector<int> v[N];
queue<int> q;
int n, st, ed, k, res, save;
int a[N];

int main(){
	cin >> n >> st >> ed;
	st --, ed --;
	for(int x, i = 0; i < n; i ++){
		scanf("%d", &x);
		if(i + x < n) v[i].push_back(i + x);
		if(i - x >= 0) v[i].push_back(i - x);
	}
	save = st, res = -1;
	q.push(st);
	while(!q.empty()){
		res = q.front();
		q.pop();
		a[res] = 1;
		for(int i = 0; i < v[res].size(); i ++) if(!a[v[res][i]]) {
			q.push(v[res][i]);
			a[v[res][i]] = 1;
		}
		if(ed == res){
			cout << k;
			return 0;
		}
		if(res == save) k ++, save = q.back();
	}
	cout << "-1";
	return 0;
}

AC;

C - Meteor Shower S

第一次:

简单的bfs;

#include<bits/stdc++.h>
using namespace std;
const int N = 310;
queue<int> q;
int n, ti, save;
int Map[N][N], sMap[N][N], aMap[N][N], stx[50010], sty[50010], stt[50010];
void ch(int x, int y){
	aMap[x][y] = 1;
	if(Map[x][y]) return;
	if(sMap[x][y] == 0){
		cout << ti;
		exit(0);
	}
	if(!Map[x-1][y] && !aMap[x-1][y] && x-1 >= 0) {
		q.push(x-1 + y * 300);
	}
	if(!Map[x][y-1] && !aMap[x][y-1] && y-1 >= 0) {
		q.push(x + (y-1) * 300);
	}
	if(!Map[x+1][y] && !aMap[x+1][y] && x+1 <= 300) {
		q.push(x+1 + y * 300);
	}
	if(!Map[x][y+1] && !aMap[x][y+1] && y+1 <= 300) {
		q.push(x + (y+1) * 300);
	}
}
int main(){
	cin >> n;
	for(int i = 0; i < n; i ++){
		cin >> stx[i] >> sty[i] >> stt[i];
		sMap[stx[i]][sty[i]] = 1;
		if(stx[i]) sMap[stx[i] - 1][sty[i]] = 1;
		if(sty[i]) sMap[stx[i]][sty[i] - 1] = 1;
		sMap[stx[i] + 1][sty[i]] = 1;
		sMap[stx[i]][sty[i] + 1] = 1;
	}
	q.push(0);
	aMap[0][0] = 1;
	while(!q.empty()){
		int x, y;
		x = q.front() % 300;
		y = q.front() / 300;
		ch(x, y);
		if(q.front() == save){
			ti ++;
			save = q.back();
			for(int i = 0; i < n; i ++){
				if(stt[i] == ti) {
					Map[stx[i]][sty[i]] = 1;
					if(stx[i] - 1 >= 0) Map[stx[i]-1][sty[i]] = 1;
					if(sty[i] - 1 >= 0) Map[stx[i]][sty[i]-1] = 1;
					if(stx[i] + 1 <= 300) Map[stx[i]+1][sty[i]] = 1;
					if(sty[i] + 1 <= 300) Map[stx[i]][sty[i]+1] = 1;
				}
			}
		}q.pop();
	}cout << "-1";
}

 一个MLE一个WA;

优化了bfs的判定:

#include<bits/stdc++.h>
using namespace std;
const int N = 310;
queue<int> q;
int n, ti, save;
int Map[N][N], sMap[N][N], aMap[N][N], stx[50010], sty[50010], stt[50010];
void ch(int x, int y){
	//cout << x << ' ' << y << endl;
	if(Map[x][y]) return;
	if(sMap[x][y] == 0){
		cout << ti;
		exit(0);
	}
	if(!Map[x-1][y] && !aMap[x-1][y] && x-1 >= 0) {
		aMap[x-1][y] = 1;
		q.push(x-1 + y * 300);
	}
	if(!Map[x][y-1] && !aMap[x][y-1] && y-1 >= 0) {
		aMap[x][y-1] = 1;
		q.push(x + (y-1) * 300);
	}
	if(!Map[x+1][y] && !aMap[x+1][y] && x+1 <= 300) {
		aMap[x+1][y] = 1;
		q.push(x+1 + y * 300);
	}
	if(!Map[x][y+1] && !aMap[x][y+1] && y+1 <= 300) {
		aMap[x][y+1] = 1;
		q.push(x + (y+1) * 300);
	}
}
int main(){
	cin >> n;
	for(int i = 0; i < n; i ++){
		cin >> stx[i] >> sty[i] >> stt[i];
		sMap[stx[i]][sty[i]] = 1;
		if(stx[i]) sMap[stx[i] - 1][sty[i]] = 1;
		if(sty[i]) sMap[stx[i]][sty[i] - 1] = 1;
		sMap[stx[i] + 1][sty[i]] = 1;
		sMap[stx[i]][sty[i] + 1] = 1;
	}
	q.push(0);
	aMap[0][0] = 1;
	while(!q.empty()){
		int x, y;
		x = q.front() % 300;
		y = q.front() / 300;
		ch(x, y);
		if(q.front() == save){
			ti ++;
			save = q.back();
			for(int i = 0; i < n; i ++){
				if(stt[i] == ti) {
					Map[stx[i]][sty[i]] = 1;
					if(stx[i] - 1 >= 0) Map[stx[i]-1][sty[i]] = 1;
					if(sty[i] - 1 >= 0) Map[stx[i]][sty[i]-1] = 1;
					if(stx[i] + 1 <= 300) Map[stx[i]+1][sty[i]] = 1;
					if(sty[i] + 1 <= 300) Map[stx[i]][sty[i]+1] = 1;
				}
			}
		}q.pop();
	}cout << "-1";
}

1WA; 

发现我可以走到(300,300)的外面:

过了

#include<bits/stdc++.h>
using namespace std;
const int N = 310;
queue<int> q;
int n, ti, save;
int Map[N][N], sMap[N][N], aMap[N][N], stx[50010], sty[50010], stt[50010];
void ch(int x, int y){
	if(Map[x][y]) return;
	if(sMap[x][y] == 0){
		cout << ti;
		exit(0);
	}
	if(!Map[x-1][y] && !aMap[x-1][y] && x-1 >= 0) {
		aMap[x-1][y] = 1;
		q.push(x-1 + y * 310);
	}
	if(!Map[x][y-1] && !aMap[x][y-1] && y-1 >= 0) {
		aMap[x][y-1] = 1;
		q.push(x + (y-1) * 310);
	}
	if(!Map[x+1][y] && !aMap[x+1][y]) {
		aMap[x+1][y] = 1;
		q.push(x+1 + y * 310);
	}
	if(!Map[x][y+1] && !aMap[x][y+1]) {
		aMap[x][y+1] = 1;
		q.push(x + (y+1) * 310);
	}
}
int main(){
	cin >> n;
	for(int i = 0; i < n; i ++){
		int x, y, t;
		cin >> x >> y >> t;
		stx[i] = x, sty[i] = y, stt[i] = t;
		sMap[stx[i]][sty[i]] = 1;
		if(stx[i]) sMap[stx[i] - 1][sty[i]] = 1;
		if(sty[i]) sMap[stx[i]][sty[i] - 1] = 1;
		sMap[stx[i] + 1][sty[i]] = 1;
		sMap[stx[i]][sty[i] + 1] = 1;
	}q.push(0);
	aMap[0][0] = 1;
	while(!q.empty()){
		int x, y;
		x = q.front() % 310;
		y = q.front() / 310;
		ch(x, y);
		if(q.front() == save){
			ti ++;
			save = q.back();
			for(int i = 0; i < n; i ++){
				if(stt[i] == ti) {
					Map[stx[i]][sty[i]] = 1;
					if(stx[i] - 1 >= 0) Map[stx[i]-1][sty[i]] = 1;
					if(sty[i] - 1 >= 0) Map[stx[i]][sty[i]-1] = 1;
					Map[stx[i]+1][sty[i]] = 1;
					Map[stx[i]][sty[i]+1] = 1;
				}
			}
		}q.pop();
	}cout << "-1";
}

D - 选数

一次过

#include<bits/stdc++.h>
using namespace std;
const int N = 30;
vector<int> v[N];
int n, k, res, ti, sum;
int a[N], arr[N];
int Is(int num){
	for(int i = 2; i <= (int)sqrt(num); i ++)
		if(num % i == 0) return 0;
	return 1;
}
void dfs(int num){
	arr[num] = 1;
	ti ++;
	sum += a[num];
	if(ti == k){
		if(Is(sum)) res ++;
	}
	else{
		for(int i = 0; i < v[num].size(); i ++)
			if(!arr[v[num][i]] && n - v[num][i] + ti >= k) dfs(v[num][i]);
	}sum -= a[num];
	ti --;
	arr[num] = 0;
}
int main(){
	cin >> n >> k;
	for(int i = 0; i < n; i ++){
		cin >> a[i];
		for(int t = 0; t < i; t ++){
			v[t].push_back(i);
		}
	}for(int i = 0; i <= n - k; i ++){
		ti = 0;
		dfs(i);
	}
	cout << res;
}

E - PERKET

第一次过了(n^2):

#include<bits/stdc++.h>
using namespace std;
int n, suan = 1, ku, res = 114514;
int s[11], k[11], a[11];
void dfs(int num){
	if(num <= n){
		for(int i = 0; i < n; i ++){
			if(!a[i]){
				suan *= s[i];
				ku += k[i];
				a[i] = 1;
				res = min(res, abs(suan - ku));
				dfs(num + 1);
				suan /= s[i];
				ku -= k[i];
				a[i] = 0;
			}
		}
	}
}
int main(){
	cin >> n;
	for(int i = 0; i < n; i ++)
		cin >> s[i] >> k[i];
	dfs(0);
	cout << res;
}

第二次优化(logn):

#include<bits/stdc++.h>
using namespace std;
int n, suan = 1, ku, res = 114514;
int s[11], k[11], a[11];
void dfs(int num){
	for(int i = num; i < n; i ++){
		if(!a[i]){
			suan *= s[i];
			ku += k[i];
			a[i] = 1;
			res = min(res, abs(suan - ku));
			dfs(num + 1);
			suan /= s[i];
			ku -= k[i];
			a[i] = 0;
		}
	}
}
int main(){
	cin >> n;
	for(int i = 0; i < n; i ++)
		cin >> s[i] >> k[i];
	dfs(0);
	cout << res;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值