week11

第一题 P1796 汤姆斯的天堂梦

最开始的想法是直接重起点开始遍历,每一个点遍历一遍,记录到当前点的最大值,再往下遍历。但发现用vector和链式前向星都不太好存,就想了个歪门,先研究每一行数据,每一行数据指的是这一行数据所代表的点,与上一行的链接关系,用很多组链接关系,每组由上一行的星球编号和权重组成,当编号为0时结束,于是,就可以重置最小值数组为最大,直接往数组里比较写入当前权重。

#include<bits/stdc++.h>
using namespace std;
int map1[200][200];
int n;
int main() {
	memset(map1, 0x3f3f3f3f, sizeof(map1));
	map1[0][1] = 0;
	cin >> n;
	int m;
	for (int i = 1; i <= n; i++) {
		cin >> m;
		for (int j = 1; j <= m; j++) {
			int s, len;
			cin >> s;
			while (s!=0) {
				cin >> len;
				map1[i][j] = min(map1[i - 1][s] + len, map1[i][j]);
				cin >> s;
			}
		}
	}
	int minn = 0x3f3f3f3f;
	for (int i = 1; i <= m; i++) {
		minn = min(minn, map1[n][i]);
	}
	cout << minn;
}

第二题 P1806 跑步

思路
手写了前八个,写到第6个的时候有了个初步思路
6=1+5,5=2+3,——》6=1+2+3
根据已有的种类替换拆出来的数字,以此得到结果
然后就是用dp来优化过程
dp[i][j]定义为第i个数在以j为开头时的种类,
dp[6][1]=6在以1拆分时能拆出1和5,5在以2为开头时dp[5][2]=1,所以dp[6][1]=2
之后dp初始化为0,然后在只有i-j>j时更新dp以限制起点比终点大的问题。

#include <bits/stdc++.h>
using namespace std;
long long dp[510][510];
int main(){

	memset(dp, 0, sizeof(dp));
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j < i; j++) {
			if (i - j > j) {
				for (int k = j + 1; k <= i - j; k++) {
					dp[i][j] += dp[i - j][k];
				}
				dp[i][j]++;
			}
			
		}
	}
	long long num = 0;
	for (int i = 1; i < n; i++) {
		num += dp[n][i];
	}
	cout << num;;
}

第四题

思路是每一个点枚举周围的点的距离,找距离相等的两个点,相等后用正方形的中点定理找第四个点,存在就更新面积
卡了两个地方,1.用中点相等找到第四个点后,此时判断出来的是平行四边形不是正方形
2.找出来的第四点会越map1的界。。。。

#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
struct node {
	int x, y;
};
struct edge
{
	int len, symbol;
};
struct cmp
{
	bool operator()(const edge a, const edge b) {
		return a.len < b.len;
	}
};
bool map1[5100][5100];
int n;
vector <node> map2;
int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		int x, y;
		cin >> x >> y;
		map2.push_back({ x,y });
		map1[x][y] = 1;
	}
	int maxs = 0;
	for (int i = 0; i < map2.size(); i++) {
		priority_queue<edge,vector<edge>,cmp> len;
		node a, b;
		a = map2[i];
		for (int j = 0; j < map2.size(); j++) {
			b = map2[j];
			len.push({ (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y),j });
		}
		int temp = len.top().len;
		int temps = len.top().symbol;
		len.pop();
		while(!len.empty()) {
			int top = len.top().len;
			int tops = len.top().symbol;
			len.pop();
			if (temp == top) {
				//有相等的边
				if (map2[temps].x + map2[tops].x - map2[i].x >= 0 && map2[temps].y + map2[tops].y - map2[i].y >= 0&& map2[temps].x + map2[tops].x - map2[i].x <= 5000&& map2[temps].y + map2[tops].y - map2[i].y <= 5000) {
					if (map1[map2[temps].x + map2[tops].x - map2[i].x][map2[temps].y + map2[tops].y - map2[i].y]) {
						if (temp + top == ((map2[temps].x - map2[tops].x)* (map2[temps].x - map2[tops].x)+ (map2[temps].y - map2[tops].y)*(map2[temps].y - map2[tops].y))) {
							maxs = max(maxs, temp);
						}
					}
				}
			}
			temp = top;
			temps = tops;
		}
	}
	cout << maxs;
}

P8794 [蓝桥杯 2022 国 A] 环境治理

本来想写dij的,但一看数据量,咱直接写flord了,而且整合flo要用一个二维数组来存,而每一天的数据本身也要更新,多完美。之后在叠个二分压时间就ok。

#include <bits/stdc++.h>
using namespace std;
int n,q;
int mapn[110][110];
int map1[110][110];
int flo[110][110];
int down[110];
int main() {
	cin >> n >> q;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> map1[i][j];
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> mapn[i][j];
		}
	}
	int p=0;
	long long l = 0, r = 1000000000,mid;
	long long ans = 10000000;
	while (l<=r) {
		mid = (l + r) / 2;
		//mid 当前天数
		int p = 0, op = mid - n * (mid / n);
		for (int i = 1; i <= n; i++)
			down[i] = mid / n + bool(i <= op);
		for (int i = 1; i <= n; i++)
			flo[i][i] = 0;
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
				flo[i][j] = max(map1[i][j] - down[i] - down[j], mapn[i][j]);
		for (int k = 1; k <= n; k++)
			for (int i = 1; i <= n; i++)
				for (int j = 1; j <= n; j++)
					flo[i][j] = min(flo[i][j], flo[i][k] + flo[k][j]);
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
				p += flo[i][j];
		if (p <= q) {
			ans = min(ans, mid);
			r = mid - 1;
		}
		else {
			l = mid + 1;
		}
	}
	if (l == 1000000000) {
		cout << "-1" << endl;
	}
	else {
		cout << ans;
	}
}

P8742 [蓝桥杯 2021 省 AB] 砝码称重

设读入了i个砝码,dp[j]带表j重量能不能被称出
一个砝码一个砝码的遍历,每次遍历更新一轮dp
转移方程dp[j]=dp[j-/+w[i]]
由于每一次只加一个砝码,其正确性可证

#include <bits/stdc++.h>
using namespace std;
int dp[100010], a[110];
int sum = 0, ans = 0;
int main()
{
	int n;
	cin >> n;
	fill(dp, dp + 100010, 0);
	dp[0] = 1;
	for (int i = 0; i < n; i++)
		cin >> a[i], sum += a[i];
	for (int i = 0; i < n; i++) {
		for (int j = sum; j >= a[i]; j--) { 
			if (dp[j - a[i]] == 1 && dp[j] != 1)
				dp[j] = 1, ans++;
		}
	}
	for (int i = 0; i < n; i++) {
		for (int j = 1; j <= sum - a[i]; j++) { 
			if (dp[j + a[i]] == 1 && dp[j] == 0)
				dp[j] = 1, ans++;
		}
	}
	cout << ans;
	return 0;
}

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值