计算概论A代码总结(基础算法类)++

对基础算法类做一个小的总结汇总

1.拼装模型(最小哈夫曼树)

//拼装模型,最小哈夫曼树
#include<iostream>
#include<queue>
using namespace std;
int main() {
	priority_queue<int, vector<int>, greater<int>> q;
	int n;
	cin >> n;
	int a;
	for (int i = 1; i <= n; i++) {
		cin >> a;
		q.push(a);
	}
	int ans = 0;
	while (q.size() > 1) {
		int a = q.top();
		q.pop();
		int b = q.top();
		q.pop();
		ans += a + b;
		q.push(a + b);
	}
	cout << ans << endl; return 0;
}

2.括号配对


//括号配对:这怎么能是个DFS呢
#include<iostream>
using namespace std;
void dfs(int cnt, int n, char *c, int l) {
	if (!cnt && !n) {//左括号全都用完,全部括号完成了配对
		cout << c << endl;
		return;
	}
	if (cnt < n) {
		c[l] = '(';
		dfs(cnt + 1, n, c, l + 1);
		c[l] = '\0';
	}
	if (cnt) {//只要有左括号,就要用右括号配上
		c[l] = ')';
		dfs(cnt - 1, n - 1, c, l + 1);
		c[l] = '\0';
	}
}
const int maxn = 1000;
int main() {
	int n = 0;
	char ans[maxn] = "";
	cin >> n;
	dfs(0, n, ans, 0);
//	return 0;

3.扔鸡蛋问题(解法1:DP)

//扔鸡蛋问题
#include<iostream>
#include<cmath>
#include<algorithm>
const int maxn = 100;
using namespace std;
int dp[maxn][maxn];
int n, m;
int main() {
	cin >> n >> m;//n是楼层,m是鸡蛋
	memset(dp, 0, sizeof(0));
	for (int j = 1; j <= n; j++) {
		dp[1][j] = j;
	}
	for (int i = 1; i <= m; i++) {
		dp[i][1] = 1;
	}
	for (int i = 2; i <= m; i++) {
		for (int j = 2; j <= n; j++) {
			int ans = 10000000;
			for (int t = 1; t <= j; t++) {
				int temp = max(dp[i - 1][j - t], dp[i][t - 1]);
				ans = min(temp, ans);
			}
			dp[i][j] = 1 + ans;
		}
	}
	cout << dp[m][n]; return 0;
}

解法2(优化DP)

//扔鸡蛋问题的算法优化:i个鸡蛋扔j次,dp[i][j]存的是
#include<iostream>
using namespace std;
int dp[21][901];
int n, m;
int main() {
	for (int i = 0; i <=910; i++) {
		dp[0][i] = 0;
		dp[1][i] = i;
	}
	for (int i = 1; i <= 20; i++) {
		dp[i][0] = 0;
		dp[i][1] = 1;
	}
	for (int i = 2; i <= 20; i++) {
		for (int j = 2; j <= 900; j++) {
			dp[i][j] = 1 + dp[i - 1][j - 1] + dp[i][j - 1];
		}
	}
	while (cin >> n >> m) {
		if (m > 20)m = 20;//大于20一定多于有效鸡蛋数
		for (int i = 1; i <= 900; i++) {
			if (dp[m][i] <= n && dp[m][i + 1] >= n) {
				cout << i + 1 << endl; break;
			}
		}
	}
}

4.子串相似度

(DP)

子串的相似度
#include<iostream>
#include<cmath>
#include<algorithm>
#include<string>
using namespace std;
const int maxn = 100;
string s1, s2;
int dp[maxn][maxn];
int main() {
	int n;
	cin >> n;
	while (n--) {
		cin >> s1 >> s2;
		int l1 = s1.length();
		int l2 = s2.length();
		memset(dp, 0, sizeof(dp));
		for (int i = 0; i <= l1; i++) {
			dp[i][0] = i;
		}
		for (int j = 0; j <= l2; j++) {
			dp[0][j] = j;
		}
		for (int i = 1; i <= l1; i++) {
			for (int j = 1; j <= l2; j++) {
				if (s1[i - 1] == s2[j - 1]) {
					dp[i][j] = dp[i - 1][j - 1]+1;//lcs中要求必须是连续的
				}
				else {
					dp[i][j] = min(min(dp[i - 1][j], dp[i][j - 1]),dp[i-1][j-1])+1;//
				}
			}
		}
		int dis = dp[l1][l2] + 1;
		printf("%.6lf\n", 1 / double(dis));
	}
	return 0;

}

5.矩阵连乘(DP)(区间dp之先河)

//矩阵连乘:经典区间DP算法默写
#include<iostream>
#include<algorithm>
#include<cmath>
const int maxn = 100;
int p[maxn];
int dp[maxn][maxn];
using namespace std;
int main() {
	int n;
	cin >> n;
	for (int i = 0; i <= n; i++) {
		cin >> p[i];
	}
	memset(dp, 0, sizeof(dp)); int ans;
	for (int l = 2; l <= n; l++) {
		for (int i = 1; i <= n; i++) {
			int j = i + l-1;//就是这里极其奇怪
			if (j > n)break;//从根源解决问题
			ans = 1 << 30;//大体算法逻辑没问题的话其实主要就是改这两个地方
			for (int k = i; k < j; k++) {//保证两侧都取等,根据具体问题可以分析出来
				ans = min(ans, dp[i][k] + dp[k + 1][j] + p[i - 1] * p[k]*p[j]);
			}
			dp[i][j] = ans;
		}
	}
	cout << dp[1][n];
}

6.最小外包矩形


//最小外包矩形
//最小外包矩形
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define N 10000
int main() {
	struct trxy {
		int flag;
		int xmin;
		int xmax;
		int ymin;
		int ymax;
	};
	struct trxy t[20];
	for (int i = 0; i < 20; i++)
	{
		t[i] = { 0, N, 0, N, 0 };
	}//牵扯到结构体变量的初始化,先定义结构体,再进行初始化
	int n;
	cin >> n;//太过着急反而忘记了输入
	int a = 0; int b = 0; int c = 0;
	for (int i = 1; i <= n; i++) {
		cin >> a >> b >> c;//用输入的数作为指标,不受循环限制
		t[a].flag = 1;
		t[a].xmax = max(t[a].xmax, b);
		t[a].xmin = min(t[a].xmin, b);
		t[a].ymax = max(t[a].ymax, c);
		t[a].ymin = min(t[a].ymin, c);
	}
	for (int i = 1; i < 20; i++) {//对于输出的考量。没说矩形的序号小于等于n;没到序号20别随意输出阿
		if (t[i].flag) {//由此也可见结构体确实会自主赋值
			cout << i << ' ';
			cout << t[i].xmin << ' ' << t[i].ymin << ' ' << t[i].xmax << ' ' << t[i].ymax << endl;
		}//越是简单题越要小心,输出是否有误
	}
	return 0;
}

7.最长平台

最长平台
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100;
int a[N];
int main() {
	int n;
	while (cin >> n) {
		if (n == 0) { cout << endl; return 0; }
		for (int i = 0; i < n; i++) {
			cin >> a[i];
		}
		int ans = 0; int x = 1;
		for (int i = 1; i < n; i++) {
			if (a[i] == a[i - 1]) {
				x++;
				ans = max(ans, x);
			}
			else {
				x = 1;
			}
		}
		cout << ans << endl;
	}
}

8.最长非负子区间

//最长非负子区间;加入循环子区间(其实就是把数组个数+1)
//这题还可以练习一下持续输入,这种题需要每次把数组清零
#include<iostream>
#include<algorithm>
#include<cmath>
const int N = 1000;
int a[N]; int b[N]; int s[N];
using namespace std;
int main() {
	int n;
	while (cin >> n) {
		for (int i = 0; i < n; i++) {
			cin >> a[i] >> b[i];
			s[i] = a[i] - b[i];
			s[n + i] = s[i];
		}
		int ans = 0; int sum = 0; int num = 0;
		for (int i = 0; i < 2 * n; i++) {
			sum += s[i];//每每取负,从新开始,因为不可能出现前面少几个负数结果更大的(画个图演示以下即可),否则这在前面就会因为sum《0被清除,优有点像最长子序列和
			num++; 
			if (sum < 0) {
				num = 0; sum = 0;
			}
			ans = max(ans, num);

		}
		cout << min(n, ans) << endl;//最大就是n了,但是因为上述是加了一个圈,可能超过n减去取最小即可
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值