第一题 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;
}