P1796 汤姆斯的天堂梦
题目描述
汤姆斯生活在一个等级为 00 的星球上。那里的环境极其恶劣,每天 1212 小时的工作和成堆的垃圾让人忍无可忍。他向往着等级为 NN 的星球上天堂般的生活。
有一些航班将人从低等级的星球送上高一级的星球,有时需要向驾驶员支付一定金额的费用,有时却又可以得到一定的金钱。
汤姆斯预先知道了从 00 等级星球去 NN 等级星球所有的航线和需要支付(或者可以得到)的金钱,他想寻找一条价格最低(甚至获得金钱最多)的航线。
输入格式
第一行一个正整数 NN(N \le 100N≤100),接下来的数据可分为 NN 个段落,每段的第一行一个整数 K_iKi(K_i \le 100Ki≤100),表示等级为 ii 的星球有 K_iKi 个。
接下来的 K_iKi 行中第 jj 行依次表示与等级为 ii,编号为 jj 的星球相连的等级为 i - 1i−1 的星球的编号和此航线需要的费用(正数表示支出,负数表示收益,费用的绝对值不超过 10001000)。
每行以 00 结束,每行的航线数 \le 100≤100。
输出格式
输出所需(或所得)费用。正数表示支出,负数表示收益。
输入输出样例
输入 #1复制
3
2
1 15 0
1 5 0
3
1 -5 2 10 0
1 3 0
2 40 0
2
1 1 2 5 3 -5 0
2 -19 3 -20 0
输出 #1复制
-1
说明/提示
对于 100 \%100% 的数据,1 \le N \le 1001≤N≤100,1 \le K_i \le 1001≤Ki≤100。
样例解释:
![](https://i-blog.csdnimg.cn/blog_migrate/9fd0f5c8bc95a8ba394bbfd77afe3b3f.jpeg)
这道题没看图直接看题目看了好久才弄明白数据的含义(太菜,人麻了),先翻译一下输入数据含义
数据分为3个段落
等级为1的星球有2个
与等级为1,编号为1的星球相连的等级为0的星球的编号和航班需要的费用分别为1,15
与等级为1,编号为2的星球相连的等级为0的星球的编号和航班需要的费用分别为1,5
等级为2的星球有3个
与等级为2,编号为1的星球相连的等级为1的星球的编号和航班需要的费用分别为1,-5
与等级为2,编号为1的星球相连的等级为1的星球的编号和航班需要的费用分别为2,10
与等级为2,编号为2的星球相连的等级为1的星球的编号和航班需要的费用分别为1,3
与等级为2,编号为3的星球相连的等级为1的星球的编号和航班需要的费用分别为2,40
等级为3的星球有2个
与等级为3,编号为1的星球相连的等级为2的星球的编号和航班需要的费用分别为1,1
与等级为3,编号为1的星球相连的等级为2的星球的编号和航班需要的费用分别为2,5
与等级为3,编号为1的星球相连的等级为2的星球的编号和航班需要的费用分别为3,5
与等级为3,编号为2的星球相连的等级为2的星球的编号和航班需要的费用分别为2,-19
与等级为3,编号为2的星球相连的等级为2的星球的编号和航班需要的费用分别为3,-20
看到提示的图可以用动态规划来求解,找到状态转移方程:f[i][j] = min(f[i][j], f[i - 1][num] + w)
i表示等级,j是编号,取第i-1级编号为num的星球到第i级编号为j的星球费用的最小值,f[i][j]表示i-1级星球到i级编号为j的星球的费用
#include<bits/stdc++.h>
using namespace std;
int f[103][103],ans,n,INF=0x3f3f3f3f;
int main()
{
cin >> n;
int k,num,w;
for (int i = 1; i <= n; i++) {//等级
cin >> k;
for (int j = 1; j <= k; j++)//编号
{
f[i][j] = INF;
cin >> num;
while (num != 0)//结束条件
{
cin >> w;
f[i][j] = min(f[i][j], f[i - 1][num] + w);
cin >> num;
}
}
}
ans = INF;
for (int i = 1; i <= k; i++)//k此时的值是最后一级星球个数
ans = min(ans, f[n][i]);//取倒数第二级星球到最后一级星球费用的最小值
cout << ans;
return 0;
}
P1806 跑步
题目描述
路人甲准备跑 nn 圈来锻炼自己的身体,他准备分多次(\gt1>1)跑完,每次都跑正整数圈,然后休息下再继续跑。
为了有效地提高自己的体能,他决定每次跑的圈数都必须比上次跑的多。
可以假设他刚开始跑了 00 圈,那么请问他可以有多少种跑完这 nn 圈的方案?
输入格式
一行一个整数,代表 nn。
输出格式
一个整数表示跑完这 nn 圈的方案数。
输入输出样例
输入 #1复制
212
输出 #1复制
995645335
说明/提示
数据规模与约定
对于 100\%100% 的数据,保证 5\le n\le 5005≤n≤500。
状态转移方程f[i][j](跑了i圈最后一次跑j圈) += f[i - j][k](当跑了i圈且这次跑j圈,上一次肯定跑k圈,k<j);
题解 P1806 【跑步】 - 草1药人 的博客 - 洛谷博客 (luogu.com.cn)
#include<bits/stdc++.h>
using namespace std;
long long n, f[505][505],ans;
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)f[i][i] = 1;
for (int i = 1; i <= n; i++)//跑的总圈数
for (int j = 1; j < i; j++)//最后一次跑的圈数
for (int k = 1; k < j&& j + k <= i; k++)//倒数第二次跑的圈数
f[i][j] += f[i - j][k];
for (int i = 1; i < n; i++)ans += f[n][i];//跑n圈的总方案数目(不管最后一次跑多少圈)
cout << ans;
return 0;
}
P8742 [蓝桥杯 2021 省 AB] 砝码称重
题目描述
你有一架天平和 NN 个砝码, 这 NN 个砝码重量依次是 W_{1}, W_{2}, \cdots, W_{N}W1,W2,⋯,WN 。 请你计算一共可以称出多少种不同的重量?
注意砝码可以放在天平两边。
输入格式
输入的第一行包含一个整数 NN 。
第二行包含 NN 个整数: W_{1}, W_{2}, W_{3}, \cdots, W_{N}W1,W2,W3,⋯,WN 。
输出格式
输出一个整数代表答案。
输入输出样例
输入 #1复制
3
1 4 6
输出 #1复制
10
说明/提示
【样例说明】
能称出的 10 种重量是: 1 、 2 、 3 、 4 、 5 、 6 、 7 、 9 、 10 、 111、2、3、4、5、6、7、9、10、11 。
\begin{aligned} &1=1 \\ &2=6-4(\text { 天平一边放 } 6, \text { 另一边放 4) } \\ &3=4-1 \\ &4=4 \\ &5=6-1 \\ &6=6 \\ &7=1+6 \\ &9=4+6-1 \\ &10=4+6 \\ &11=1+4+6 \end{aligned}1=12=6−4( 天平一边放 6, 另一边放 4) 3=4−14=45=6−16=67=1+69=4+6−110=4+611=1+4+6
【评测用例规模与约定】
对于 50 \%50% 的评测用例, 1 \leq N \leq 151≤N≤15 。
对于所有评测用例, 1 \leq N \leq 100, N1≤N≤100,N 个砝码总重不超过 10^5105。
蓝桥杯 2021 第一轮省赛 A 组 F 题(B 组 G 题)。
砝码有两种放置方法:1.放右边:f[j]=max(f[j],f[j-w[i]]);
2.放左边:f[j]=max(f[j],f[j+w[i]]);
其中f[j]表示重量j能否称出来,w[i]表示每个砝码的重量。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+3;
long long n, f[maxn], ans,w[103];
int main()
{
cin >> n;
for (ll i = 1; i <= n; i++)cin >> w[i];
f[0] = 1;
for (ll i = 1; i <= n; i++)
for (ll j = maxn; j >= w[i]; j--)
f[j] = max(f[j], f[j- w[i]]);
for (ll i = 1; i <= n; i++)
for (ll j = 1; j < maxn - w[i]; j++)
f[j] = max(f[j], f[j + w[i]]);
for (ll i = 1; i <= maxn; i++)ans += f[i];//计数
cout << ans<<endl;
return 0;
}
P1959 遗址
题目描述
很久很久以前有一座寺庙,从上往下看寺庙的形状正好是一个正方形,由 44 个角上竖立的圆柱搭建而成。现在圆柱都倒塌了,只在地上留下圆形的痕迹,可是现在地上有很多这样的痕迹,专家说一定是最大的那个。
写一个程序,给出圆柱的坐标,找出由 44 个圆柱构成的最大的正方形,因为这就是寺庙的位置,要求计算出最大的面积。注意正方形的边不一定平行于坐标轴。
例如图有 1010 根柱子,其中 (4,2),(5,2),(5,3),(4,3)(4,2),(5,2),(5,3),(4,3) 可以形成一个正方形,(1,1),(4,0),(5,3),(2,4)(1,1),(4,0),(5,3),(2,4) 也可以,后者是其中最大的,面积为 1010。
![](https://i-blog.csdnimg.cn/blog_migrate/b658150b61e9cafa4ff5c4827ad1b9da.jpeg)
输入格式
第一行包含一个 N(1\leq N\leq 3000)N(1≤N≤3000),表示柱子的数量。
接下来 NN 行,每行有两个空格隔开的整数表示柱子的坐标(坐标值在 00 到 50005000 之间),柱子的位置互不相同。
输出格式
如果存在正方形,输出最大的面积,否则输出 00。
输入输出样例
输入 #1复制
10
9 4
4 3
1 1
4 2
2 4
5 8
4 0
5 3
0 5
5 2
输出 #1复制
10
说明/提示
【数据范围】
30\%30% 满足:1\leq N \leq1001≤N≤100。
60\%60% 满足:1\leq N \leq5001≤N≤500。
100\%100% 满足:1\leq N \leq30001≤N≤3000。
需要一定的数学知识,如果一个个地去枚举点会超时,找到两个点后指定一个方向来计算正方形其他点的坐标
P1959 - cyx2009 的博客 - 洛谷博客 (luogu.com.cn)
![](https://i-blog.csdnimg.cn/blog_migrate/972cf688f333c13c4405ebbe203ced5d.png)
#include<bits/stdc++.h>
using namespace std;
bool f[5003][5003];
int n, x[3003], y[3003],ans;
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> x[i] >> y[i];
f[x[i]][y[i]] = 1;
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
int dx = x[i] - x[j];
int dy = y[i] - y[j];
int x1 = x[i] - dy;
int x2 = x[j] - dy;
int y1 = y[i] + dx;
int y2 = y[j] + dx;
if (x1 < 0 || x1>5000 || x2 < 0 || x2>5000 || y1 < 0 || y1>5000 || y2 < 0 || y2>5000)continue;//判断下标是否合法
if (f[x1][y1] && f[x2][y2])
{
ans = max(ans, dx * dx + dy * dy);
}
}
}
cout << ans << endl;
return 0;
}
P8794 [蓝桥杯 2022 国 A] 环境治理
题目描述
LQ 国拥有 nn 个城市,从 00 到 n - 1n−1 编号,这 nn 个城市两两之间都有且仅有一条双向道路连接,这意味着任意两个城市之间都是可达的。每条道路都有一个属性 DD,表示这条道路的灰尘度。当从一个城市 A 前往另一个城市 B 时,可能存在多条路线,每条路线的灰尘度定义为这条路线所经过的所有道路的灰尘度之和,LQ 国的人都很讨厌灰尘,所以他们总会优先选择灰尘度最小的路线。
LQ 国很看重居民的出行环境,他们用一个指标 PP 来衡量 LQ 国的出行环境,PP 定义为:
P=\sum \limits_{i=0}^{n-1} \sum \limits_{j=0}^{n-1} d(i,j)P=i=0∑n−1j=0∑n−1d(i,j)
其中 d(i,j)d(i,j) 表示城市 ii 到城市 jj 之间灰尘度最小的路线对应的灰尘度的值。
为了改善出行环境,每个城市都要有所作为,当某个城市进行道路改善时,会将与这个城市直接相连的所有道路的灰尘度都减少 11,但每条道路都有一个灰尘度的下限值 LL,当灰尘度达到道路的下限值时,无论再怎么改善,道路的灰尘度也不会再减小了。
具体的计划是这样的:
第 11 天,00 号城市对与其直接相连的道路环境进行改善;
第 22 天,11 号城市对与其直接相连的道路环境进行改善;
……
第 nn 天,n - 1n−1 号城市对与其直接相连的道路环境进行改善;
第 n + 1n+1 天,00 号城市对与其直接相连的道路环境进行改善;
第 n + 2n+2 天,11 号城市对与其直接相连的道路环境进行改善;
……
LQ 国想要使得 PP 指标满足 P \leq QP≤Q。请问最少要经过多少天之后,PP 指标可以满足 P \leq QP≤Q。如果在初始时就已经满足条件,则输出 00;如果永远不可能满足,则输出 -1−1。
输入格式
输入的第一行包含两个整数 n, Qn,Q,用一个空格分隔,分别表示城市个数和期望达到的 PP 指标。
接下来 nn 行,每行包含 nn 个整数,相邻两个整数之间用一个空格分隔,其中第 ii 行第 jj 列的值 D_{i,j} (D_{i,j}=D_{j,i},D_{i,i} = 0)Di,j(Di,j=Dj,i,Di,i=0) 表示城市 ii 与城市 jj 之间直接相连的那条道路的灰尘度。
接下来 nn 行,每行包含 nn 个整数,相邻两个整数之间用一个空格分隔,其中第 ii 行第 jj 列的值 L_{i,j} (L_{i,j} = L_{j,i}, L_{i,i} = 0)Li,j(Li,j=Lj,i,Li,i=0) 表示城市 ii 与城市 jj 之间直接相连的那条道路的灰尘度的下限值。
输出格式
输出一行包含一个整数表示答案。
输入输出样例
输入 #1复制
3 10
0 2 4
2 0 1
4 1 0
0 2 2
2 0 0
2 0 0
输出 #1复制
2
说明/提示
【样例说明】
初始时的图如下所示,每条边上的数字表示这条道路的灰尘度:
![](https://i-blog.csdnimg.cn/blog_migrate/61cbce68d8838261d945f9bb7e98a901.png)
此时每对顶点之间的灰尘度最小的路线对应的灰尘度为:
d(0, 0) = 0, d(0, 1) = 2, d(0, 2) = 3d(0,0)=0,d(0,1)=2,d(0,2)=3;
d(1, 0) = 2, d(1, 1) = 0, d(1, 2) = 1d(1,0)=2,d(1,1)=0,d(1,2)=1;
d(2, 0) = 3, d(2, 1) = 1, d(2, 2) = 0d(2,0)=3,d(2,1)=1,d(2,2)=0。
初始时的 PP 指标为 (2 + 3 + 1) \times 2 = 12(2+3+1)×2=12,不满足 P \leq Q = 10P≤Q=10;
第一天,00 号城市进行道路改善,改善后的图示如下:
![](https://i-blog.csdnimg.cn/blog_migrate/4891024de8640b9210a1fa6b3cb771ff.png)
注意到边 (0, 2)(0,2) 的值减小了 11,但 (0, 1)(0,1) 并没有减小,因为 L_{0,1} = 2L0,1=2 ,所以 (0, 1)(0,1) 的值不可以再减小了。此时每对顶点之间的灰尘度最小的路线对应的灰尘度为:
d(0, 0) = 0, d(0, 1) = 2, d(0, 2) = 3d(0,0)=0,d(0,1)=2,d(0,2)=3,
d(1, 0) = 2, d(1, 1) = 0, d(1, 2) = 1d(1,0)=2,d(1,1)=0,d(1,2)=1,
d(2, 0) = 3, d(2, 1) = 1, d(2, 2) = 0d(2,0)=3,d(2,1)=1,d(2,2)=0。
此时 PP 仍为 1212。
第二天,1 号城市进行道路改善,改善后的图示如下:
![](https://i-blog.csdnimg.cn/blog_migrate/e382ade33600ca34cd061ed901dd72be.png)
此时每对顶点之间的灰尘度最小的路线对应的灰尘度为:
d(0, 0) = 0, d(0, 1) = 2, d(0, 2) = 2d(0,0)=0,d(0,1)=2,d(0,2)=2,
d(1, 0) = 2, d(1, 1) = 0, d(1, 2) = 0d(1,0)=2,d(1,1)=0,d(1,2)=0,
d(2, 0) = 2, d(2, 1) = 0, d(2, 2) = 0d(2,0)=2,d(2,1)=0,d(2,2)=0。
此时的 PP 指标为 (2 + 2) \times 2 = 8 < Q(2+2)×2=8<Q,此时已经满足条件。
所以答案是 22。
【评测用例规模与约定】
对于 30\%30% 的评测用例,1 \leq n \leq 101≤n≤10,0 \leq L_{i,j} \leq D_{i,j} \leq 100≤Li,j≤Di,j≤10;
对于 60\%60% 的评测用例,1 \leq n \leq 501≤n≤50,0 \leq L_{i,j} \leq D_{i,j} \leq 10^50≤Li,j≤Di,j≤105;
对于所有评测用例,1 \leq n \leq 1001≤n≤100,0 \leq L_{i,j} \leq D_{i,j} \leq 10^50≤Li,j≤Di,j≤105,0 \leq Q \leq 2^{31} - 10≤Q≤231−1。
蓝桥杯 2022 国赛 A 组 F 题。
多源最短路径采用floyed算法
#include<bits/stdc++.h>
using namespace std;
#define N 105
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define mid (l + r >> 1)
int n, Q, l, r, ans = INF;
int D[N][N], L[N][N], dis[N][N], reduce[N];
inline int check(int x) {
int t = x / n, P = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
dis[i][j] = INF;
for (int i = 1; i <= n; i++)
dis[i][i] = 0;
for (int i = 1; i <= n; i++)
reduce[i] = t;
for (int i = 1; i <= x - n * t; i++)
++reduce[i];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
dis[i][j] = max(L[i][j], D[i][j] - reduce[i] - reduce[j]);//与每条道路都有的一个灰尘度的下限值比较取最小值
for(int k=1;k<=n;k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
P += dis[i][j];
if (P <= Q) return 1;
else return 0;
}
signed main() {
cin >> n >> Q;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
cin >> D[i][j];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
cin >> L[i][j];
l = 0, r = INF;
while (l <= r) {
if (check(mid)) ans = min(ans, mid), r = mid - 1;
else l = mid + 1;
}
if (ans == INF) printf("-1");
else printf("%lld", ans);
return 0;
}