汤姆斯的天堂梦
题目描述
汤姆斯生活在一个等级为 0 0 0 的星球上。那里的环境极其恶劣,每天 12 12 12 小时的工作和成堆的垃圾让人忍无可忍。他向往着等级为 N N N 的星球上天堂般的生活。
有一些航班将人从低等级的星球送上高一级的星球,有时需要向驾驶员支付一定金额的费用,有时却又可以得到一定的金钱。
汤姆斯预先知道了从 0 0 0 等级星球去 N N N 等级星球所有的航线和需要支付(或者可以得到)的金钱,他想寻找一条价格最低(甚至获得金钱最多)的航线。
输入格式
第一行一个正整数 N N N( N ≤ 100 N \le 100 N≤100),接下来的数据可分为 N N N 个段落,每段的第一行一个整数 K i K_i Ki( K i ≤ 100 K_i \le 100 Ki≤100),表示等级为 i i i 的星球有 K i K_i Ki 个。
接下来的 K i K_i Ki 行中第 j j j 行依次表示与等级为 i i i,编号为 j j j 的星球相连的等级为 i − 1 i - 1 i−1 的星球的编号和此航线需要的费用(正数表示支出,负数表示收益,费用的绝对值不超过 1000 1000 1000)。
每行以 0 0 0 结束,每行的航线数 ≤ 100 \le 100 ≤100。
输出格式
输出所需(或所得)费用。正数表示支出,负数表示收益。
样例 #1
样例输入 #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 \% 100% 的数据, 1 ≤ N ≤ 100 1 \le N \le 100 1≤N≤100, 1 ≤ K i ≤ 100 1 \le K_i \le 100 1≤Ki≤100。
样例解释:
这道题输入的时候要注意判断a是不是0
f [ i ] [ j ] 表示第i等级的第j号星球 存的是最小路费
这个状态如何得到呢
只要遍历上一个等级 也就是 i - 1 级的所有星球 将到达i - 1级的星球的路费 加上 该星球到现在所求星球的这段距离的路费 求这一系列路费当中最小的一个
所以在dp之前也必须给所有f [ i ] [ j ] 初始化赋上一个极大值 才能保证 至少得有一条路是能走到目标等级的 不然如果 f [ i ] [ j ] 的状态一直不被更新 那就一直是与i - 1 级的星球断开连接的状态
最后找出最高等级星球中最省钱的一个就行
#include <bits/stdc++.h>
using namespace std;
int f[201][201];
int b, c;
int main()
{
int n, a;
cin >> n;
for (int i = 1; i <= n; ++i)
{
cin >> a;
for (int j = 1; j <= a; ++j)
{
f[i][j] = 0x3f3f3f;//初始化
cin >> b;
while (b!=0)//以0结束
{
cin >> c;
f[i][j] = min(f[i - 1][b] + c, f[i][j]);
cin >> b;
}
}
}
int ans = 0x3f3f3f;
for (int i=1; i <= a; ++i)
{
ans = min(f[n][i], ans);//在最高等级的星球里找一个最省钱的
}
cout << ans;
}
跑步
题目描述
路人甲准备跑 n n n 圈来锻炼自己的身体,他准备分多次( > 1 \gt1 >1)跑完,每次都跑正整数圈,然后休息下再继续跑。
为了有效地提高自己的体能,他决定每次跑的圈数都必须比上次跑的多。
可以假设他刚开始跑了 0 0 0 圈,那么请问他可以有多少种跑完这 n n n 圈的方案?
输入格式
一行一个整数,代表 n n n。
输出格式
一个整数表示跑完这 n n n 圈的方案数。
样例 #1
样例输入 #1
212
样例输出 #1
995645335
提示
数据规模与约定
对于 100 % 100\% 100% 的数据,保证 5 ≤ n ≤ 500 5\le n\le 500 5≤n≤500。
#include <iostream>
using namespace std;
long long n, ans[501];
int main()
{
cin >> n;
ans[0]=1;
for (int i = 1; i <= n; ++i)
for (int j = n; j >= i; --j)
ans[j] += ans[j - i];//01背包问题,跑完j圈的方案数相当于在跑i圈之前,跑完j-i圈的且以任意正整数圈结尾的总方案数
cout << ans[n] - 1 << endl;
}
[蓝桥杯 2021 省 AB] 砝码称重
题目描述
你有一架天平和 N N N 个砝码, 这 N N N 个砝码重量依次是 W 1 , W 2 , ⋯ , W N W_{1}, W_{2}, \cdots, W_{N} W1,W2,⋯,WN 。 请你计算一共可以称出多少种不同的重量?
注意砝码可以放在天平两边。
输入格式
输入的第一行包含一个整数 N N N 。
第二行包含 N N N 个整数: W 1 , W 2 , W 3 , ⋯ , W N W_{1}, W_{2}, W_{3}, \cdots, W_{N} W1,W2,W3,⋯,WN 。
输出格式
输出一个整数代表答案。
样例 #1
样例输入 #1
3
1 4 6
样例输出 #1
10
提示
【样例说明】
能称出的 10 种重量是: 1 、 2 、 3 、 4 、 5 、 6 、 7 、 9 、 10 、 11 1 、 2 、 3 、 4 、 5 、 6 、 7 、 9 、 10 、 11 1、2、3、4、5、6、7、9、10、11 。
1 = 1 2 = 6 − 4 ( 天平一边放 6 , 另一边放 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 \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 \% 50% 的评测用例, 1 ≤ N ≤ 15 1 \leq N \leq 15 1≤N≤15 。
对于所有评测用例, 1 ≤ N ≤ 100 , N 1 \leq N \leq 100, N 1≤N≤100,N 个砝码总重不超过 1 0 5 10^5 105。
蓝桥杯 2021 第一轮省赛 A 组 F 题(B 组 G 题)。
用 f [ i ] [ j ] 来表示只用前 i 个 砝码 能否称出重量 j ,存的是bool值
状态计算:
想要用前 i 个砝码称出重量 j 有三种情况
第一种:不使用第 i 个砝码 ,即只用前 i - 1 个砝码就能称出 j
第二种:把砝码放在更重的一侧,要让这种方法成立的话,就代表 只用前i - 1 个砝码就能够称出重量为abs ( j - w [ i ] )的物体,因为能够称出这个重量的话,只要把 砝码 i 放在更重的一侧 就能称出重量 j 了
第三种:把砝码放在更轻的一侧,他等于 要只用前 i - 1 个砝码称出 j + w [ i ] 那么放在更轻的一侧相当于减去 w [ i ] ,就能够称出 j 了
三种有任意一种为true,f [ i ] [ j ] 就为true
三种有任意一种为true,f [ i ] [ j ] 就为true
#include<bits/stdc++.h>
using namespace std;
int n,ans,sum,w[101];
bool dp[101][100001];
int main()
{
cin>>n;
for(int i=1;i<=n;++i){
cin>>w[i];
sum+=w[i];
}
for(int i=1;i<=n;++i)//遍历每中砝码
{
for(int j=sum;j>0;--j)//判断每个重量值是否有对应的砝码组合存在
{
if(j==w[i])dp[i][j]=1;
else if(dp[i-1][j])dp[i][j]=1;
else if(dp[i-1][j+w[i]])dp[i][j]=1;
else if(dp[i-1][abs(j-w[i])])dp[i][j]=1;
}
}
for(int i=1;i<=sum;++i)if(dp[n][i])ans++;
cout<<ans;
}
遗址
题目描述
很久很久以前有一座寺庙,从上往下看寺庙的形状正好是一个正方形,由 4 4 4 个角上竖立的圆柱搭建而成。现在圆柱都倒塌了,只在地上留下圆形的痕迹,可是现在地上有很多这样的痕迹,专家说一定是最大的那个。
写一个程序,给出圆柱的坐标,找出由 4 4 4 个圆柱构成的最大的正方形,因为这就是寺庙的位置,要求计算出最大的面积。注意正方形的边不一定平行于坐标轴。
例如图有 10 10 10 根柱子,其中 ( 4 , 2 ) , ( 5 , 2 ) , ( 5 , 3 ) , ( 4 , 3 ) (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) (1,1),(4,0),(5,3),(2,4) 也可以,后者是其中最大的,面积为 10 10 10。
暴力的思路就是枚举四个点,但是这样是必然超时的,
观察图形发现可以枚举两个点,从而推出另外两个点
先确定两个点作为正方形的一条边
如图所示,我们将左上顶点定为 i,左下顶点对应 j,那么可以发现如下关系:
标红段为 i 与 j 的横坐标差,正好为左下顶点与右下顶点的纵坐标之差。
标蓝段为 i 与 j 的纵坐标差,正好为左下顶点与右下顶点的横坐标之差。
而正方形的面积,正是 i 的平方加上 j 的平方,,勾股定理。。
如此,我们即可仅仅通过两个点推出其余两个点的坐标。
只要判断这两个推出来的点是否存在即可 存在就算面积
输入格式
第一行包含一个 N ( 1 ≤ N ≤ 3000 ) N(1\leq N\leq 3000) N(1≤N≤3000),表示柱子的数量。
接下来 N N N 行,每行有两个空格隔开的整数表示柱子的坐标(坐标值在 0 0 0 到 5000 5000 5000 之间),柱子的位置互不相同。
输出格式
如果存在正方形,输出最大的面积,否则输出 0 0 0。
样例 #1
样例输入 #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\% 30% 满足: 1 ≤ N ≤ 100 1\leq N \leq100 1≤N≤100。
60 % 60\% 60% 满足: 1 ≤ N ≤ 500 1\leq N \leq500 1≤N≤500。
100 % 100\% 100% 满足: 1 ≤ N ≤ 3000 1\leq N \leq3000 1≤N≤3000。
#include <bits/stdc++.h>
using namespace std;
bool f[5021][5031];
long long x[3021];
long long y[3021];
long long n, m;
int dx, dy, p1x, p2x, p1y, p2y;
int ans = 0;
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++)
{
dx = x[i] - x[j];
dy = y[i] - y[j];
p1x = x[i] - dy;
p2x = x[j] - dy;
p1y = y[i] + dx;
p2y = y[j] + dx;
if (p1x < 1 || p1x > 5000 || p2x < 1 || p2x > 5000 || p1y > 5000 || p1y < 1 || p2y < 1 || p2y > 5000)
continue;
if (f[p1x][p1y] && f[p2x][p2y])
{
ans = max(ans, dx * dx + dy * dy);
}
}
}
cout << ans;
}
[蓝桥杯 2022 国 A] 环境治理
题目描述
LQ 国拥有 n n n 个城市,从 0 0 0 到 n − 1 n - 1 n−1 编号,这 n n n 个城市两两之间都有且仅有一条双向道路连接,这意味着任意两个城市之间都是可达的。每条道路都有一个属性 D D D,表示这条道路的灰尘度。当从一个城市 A 前往另一个城市 B 时,可能存在多条路线,每条路线的灰尘度定义为这条路线所经过的所有道路的灰尘度之和,LQ 国的人都很讨厌灰尘,所以他们总会优先选择灰尘度最小的路线。
LQ 国很看重居民的出行环境,他们用一个指标 P P P 来衡量 LQ 国的出行环境, P P P 定义为:
P = ∑ i = 0 n − 1 ∑ j = 0 n − 1 d ( i , j ) 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) d(i,j) 表示城市 i i i 到城市 j j j 之间灰尘度最小的路线对应的灰尘度的值。
为了改善出行环境,每个城市都要有所作为,当某个城市进行道路改善时,会将与这个城市直接相连的所有道路的灰尘度都减少 1 1 1,但每条道路都有一个灰尘度的下限值 L L L,当灰尘度达到道路的下限值时,无论再怎么改善,道路的灰尘度也不会再减小了。
具体的计划是这样的:
- 第 1 1 1 天, 0 0 0 号城市对与其直接相连的道路环境进行改善;
- 第 2 2 2 天, 1 1 1 号城市对与其直接相连的道路环境进行改善;
……
- 第 n n n 天, n − 1 n - 1 n−1 号城市对与其直接相连的道路环境进行改善;
- 第 n + 1 n + 1 n+1 天, 0 0 0 号城市对与其直接相连的道路环境进行改善;
- 第 n + 2 n + 2 n+2 天, 1 1 1 号城市对与其直接相连的道路环境进行改善;
……
LQ 国想要使得 P P P 指标满足 P ≤ Q P \leq Q P≤Q。请问最少要经过多少天之后, P P P 指标可以满足 P ≤ Q P \leq Q P≤Q。如果在初始时就已经满足条件,则输出 0 0 0;如果永远不可能满足,则输出 − 1 -1 −1。
输入格式
输入的第一行包含两个整数 n , Q n, Q n,Q,用一个空格分隔,分别表示城市个数和期望达到的 P P P 指标。
接下来 n n n 行,每行包含 n n n 个整数,相邻两个整数之间用一个空格分隔,其中第 i i i 行第 j j j 列的值 D i , j ( D i , j = D j , i , D i , i = 0 ) D_{i,j} (D_{i,j}=D_{j,i},D_{i,i} = 0) Di,j(Di,j=Dj,i,Di,i=0) 表示城市 i i i 与城市 j j j 之间直接相连的那条道路的灰尘度。
接下来 n n n 行,每行包含 n n n 个整数,相邻两个整数之间用一个空格分隔,其中第 i i i 行第 j j j 列的值 L i , j ( L i , j = L j , i , L i , i = 0 ) L_{i,j} (L_{i,j} = L_{j,i}, L_{i,i} = 0) Li,j(Li,j=Lj,i,Li,i=0) 表示城市 i i i 与城市 j j j 之间直接相连的那条道路的灰尘度的下限值。
输出格式
输出一行包含一个整数表示答案。
样例 #1
样例输入 #1
3 10
0 2 4
2 0 1
4 1 0
0 2 2
2 0 0
2 0 0
样例输出 #1
2
提示
【样例说明】
初始时的图如下所示,每条边上的数字表示这条道路的灰尘度:
此时每对顶点之间的灰尘度最小的路线对应的灰尘度为:
- d ( 0 , 0 ) = 0 , d ( 0 , 1 ) = 2 , d ( 0 , 2 ) = 3 d(0, 0) = 0, d(0, 1) = 2, d(0, 2) = 3 d(0,0)=0,d(0,1)=2,d(0,2)=3;
- d ( 1 , 0 ) = 2 , d ( 1 , 1 ) = 0 , d ( 1 , 2 ) = 1 d(1, 0) = 2, d(1, 1) = 0, d(1, 2) = 1 d(1,0)=2,d(1,1)=0,d(1,2)=1;
- d ( 2 , 0 ) = 3 , d ( 2 , 1 ) = 1 , d ( 2 , 2 ) = 0 d(2, 0) = 3, d(2, 1) = 1, d(2, 2) = 0 d(2,0)=3,d(2,1)=1,d(2,2)=0。
初始时的 P P P 指标为 ( 2 + 3 + 1 ) × 2 = 12 (2 + 3 + 1) \times 2 = 12 (2+3+1)×2=12,不满足 P ≤ Q = 10 P \leq Q = 10 P≤Q=10;
第一天, 0 0 0 号城市进行道路改善,改善后的图示如下:
注意到边 ( 0 , 2 ) (0, 2) (0,2) 的值减小了 1 1 1,但 ( 0 , 1 ) (0, 1) (0,1) 并没有减小,因为 L 0 , 1 = 2 L_{0,1} = 2 L0,1=2 ,所以 ( 0 , 1 ) (0, 1) (0,1) 的值不可以再减小了。此时每对顶点之间的灰尘度最小的路线对应的灰尘度为:
- d ( 0 , 0 ) = 0 , d ( 0 , 1 ) = 2 , d ( 0 , 2 ) = 3 d(0, 0) = 0, d(0, 1) = 2, d(0, 2) = 3 d(0,0)=0,d(0,1)=2,d(0,2)=3,
- d ( 1 , 0 ) = 2 , d ( 1 , 1 ) = 0 , d ( 1 , 2 ) = 1 d(1, 0) = 2, d(1, 1) = 0, d(1, 2) = 1 d(1,0)=2,d(1,1)=0,d(1,2)=1,
- d ( 2 , 0 ) = 3 , d ( 2 , 1 ) = 1 , d ( 2 , 2 ) = 0 d(2, 0) = 3, d(2, 1) = 1, d(2, 2) = 0 d(2,0)=3,d(2,1)=1,d(2,2)=0。
此时 P P P 仍为 12 12 12。
第二天,1 号城市进行道路改善,改善后的图示如下:
此时每对顶点之间的灰尘度最小的路线对应的灰尘度为:
- d ( 0 , 0 ) = 0 , d ( 0 , 1 ) = 2 , d ( 0 , 2 ) = 2 d(0, 0) = 0, d(0, 1) = 2, d(0, 2) = 2 d(0,0)=0,d(0,1)=2,d(0,2)=2,
- d ( 1 , 0 ) = 2 , d ( 1 , 1 ) = 0 , d ( 1 , 2 ) = 0 d(1, 0) = 2, d(1, 1) = 0, d(1, 2) = 0 d(1,0)=2,d(1,1)=0,d(1,2)=0,
- d ( 2 , 0 ) = 2 , d ( 2 , 1 ) = 0 , d ( 2 , 2 ) = 0 d(2, 0) = 2, d(2, 1) = 0, d(2, 2) = 0 d(2,0)=2,d(2,1)=0,d(2,2)=0。
此时的 P P P 指标为 ( 2 + 2 ) × 2 = 8 < Q (2 + 2) \times 2 = 8 < Q (2+2)×2=8<Q,此时已经满足条件。
所以答案是 2 2 2。
【评测用例规模与约定】
- 对于 30 % 30\% 30% 的评测用例, 1 ≤ n ≤ 10 1 \leq n \leq 10 1≤n≤10, 0 ≤ L i , j ≤ D i , j ≤ 10 0 \leq L_{i,j} \leq D_{i,j} \leq 10 0≤Li,j≤Di,j≤10;
- 对于 60 % 60\% 60% 的评测用例, 1 ≤ n ≤ 50 1 \leq n \leq 50 1≤n≤50, 0 ≤ L i , j ≤ D i , j ≤ 1 0 5 0 \leq L_{i,j} \leq D_{i,j} \leq 10^5 0≤Li,j≤Di,j≤105;
- 对于所有评测用例, 1 ≤ n ≤ 100 1 \leq n \leq 100 1≤n≤100, 0 ≤ L i , j ≤ D i , j ≤ 1 0 5 0 \leq L_{i,j} \leq D_{i,j} \leq 10^5 0≤Li,j≤Di,j≤105, 0 ≤ Q ≤ 2 31 − 1 0 \leq Q \leq 2^{31} - 1 0≤Q≤231−1。
蓝桥杯 2022 国赛 A 组 F 题。
#include <bits/stdc++.h>
using namespace std;
int p();
void floyd();
bool check(int x);
bool flag;
int n, Q;
int D[105][105], L[105][105];
int f[105][105];
int main()
{
cin >> n >> Q;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> D[i][j];
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> L[i][j];
}
}
int l = 0, r = 100000; // 二分
while (l < r)
{
int mid = (l + r) / 2;
if (check(mid))
flag = 1, r = mid; // 如果有成功的flag变true
else
l = mid + 1;
}
if (!flag)
cout << -1;
else
cout << l; // 输出l
return 0;
}
int p() // 用来求P
{
int P = 0;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
P += f[i][j];
}
return P;
}
void floyd()
{
for (int i = 0; i < n; i++) // floyd求最短路
{
for (int j = 0; j < n; j++)
{
for (int k = 0; k < n; k++)
{
f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
}
}
}
return;
}
bool check(int x)
{
int clear = x / n; // 表示每个城市至少经历了多少轮治理
int city = (x - 1) % n; // 表示有哪些城市是正在进行最新一轮的治理
for (int i = 0; i < n; i++) // 先初始化
{
for (int j = 0; j < n; j++)
{
f[i][j] = D[i][j];
}
}
if (!x) // 第0天就特判一下,直接floyd
{
floyd();
if (p() <= Q)
return true;
else
return false;
}
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
int dif;
if (i <= city)
dif = clear + 1; // 序号在city之后的城市是还没有轮到最新一轮治理的,治理数会小1
else
dif = clear;
// 环境治理
if (D[i][j] - dif >= L[i][j])
{
f[i][j] = D[i][j] - dif;
f[j][i] = D[i][j] - dif;
}
else
{
f[i][j] = L[i][j];
f[j][i] = L[i][j];
}
}
}
floyd();
if (p() <= Q)
return true;
else
return false;
}