Week11

汤姆斯的天堂梦


题目描述


汤姆斯生活在一个等级为 0 的星球上。那里的环境极其恶劣,每天 12 小时的工作和成堆的垃圾让人忍无可忍。他向往着等级为 N 的星球上天堂般的生活。

有一些航班将人从低等级的星球送上高一级的星球,有时需要向驾驶员支付一定金额的费用,有时却又可以得到一定的金钱。

汤姆斯预先知道了从 0 等级星球去 N 等级星球所有的航线和需要支付(或者可以得到)的金钱,他想寻找一条价格最低(甚至获得金钱最多)的航线。

输入格式


第一行一个正整数 N(N <= 100),接下来的数据可分为 N 个段落,每段的第一行一个整数 K_i(K_i <= 100),表示等级为 i 的星球有 K_i个。

接下来的 K_i 行中第 j 行依次表示与等级为 i,编号为 j 的星球相连的等级为i - 1 的星球的编号和此航线需要的费用(正数表示支出,负数表示收益,费用的绝对值不超过 1000)。

每行以 0 结束,每行的航线数 <=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 % 的数据,1 <= N <= 100,1 <= K_i <= 100。

样例解释:

解题思路:


dp,从下往上,每一次都取最低费用,最后再在最上面一行取最低费用

完整代码如下:


#include <bits/stdc++.h>

usingnamespacestd;

constintmaxn=101,m=1e6+5;

intf[maxn][maxn];

intmain()

{

intn,k,a,b;

cin>>n;

for(inti=1; i<=n; i++){

cin>>k;

for(intj=1; j<=k; j++){

cin>>a;

f[i][j]=m; //初始化

while(a){

cin>>b;

f[i][j]=min(f[i][j],f[i-1][a]+b);//dp

cin>>a;

}

}

}

intminn=m;

for(inti=1; i<=k; i++) minn=min(f[n][i],minn);

cout<<minn;

return0;

}

跑步


题目描述


路人甲准备跑 n 圈来锻炼自己的身体,他准备分多次(>1)跑完,每次都跑正整数圈,然后休息下再继续跑。

为了有效地提高自己的体能,他决定每次跑的圈数都必须比上次跑的多。

可以假设他刚开始跑了 0 圈,那么请问他可以有多少种跑完这 n 圈的方案?

输入格式


一行一个整数,代表 n。

输出格式


一个整数表示跑完这 n 圈的方案数。

样例 #1


样例输入 #1

212

样例输出 #1

995645335

提示


数据规模与约定

对于 100% 的数据,保证 5<= n<= 500。

解题思路:


背包计数,每次跑的圈数要递增,相当于每次取的物品数要递增

完整代码如下:


#include <bits/stdc++.h>

usingnamespacestd;

constintmaxn=505;

longlongn,sum[maxn];

intmain()

{

cin>>n;

sum[0]=1;

for(inti=1; i<=n; i++){

for(intj=n; j>=i; j--){

sum[j]+=sum[j-i];

}

}

cout<<sum[n]-1;//减去初值

return0;

}

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


题目描述


你有一架天平和 N 个砝码, 这 N 个砝码重量依次是 W_1, W_2, ......, W_N 。 请你计算一共可以称出多少种不同的重量?

注意砝码可以放在天平两边。

输入格式


输入的第一行包含一个整数 $N$ 。

第二行包含 N 个整数: W_1, W_2, W_3, ......, W_N。

输出格式


输出一个整数代表答案。

样例 #1


样例输入 #1

3

1 4 6

样例输出 #1

10

提示


【样例说明】

能称出的 10 种重量是: $1 、 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}

$$

【评测用例规模与约定】

对于 50 % 的评测用例, 1 <= N <= 15 。

对于所有评测用例, 1 <= N <= 100, N 个砝码总重不超过 10^5。

蓝桥杯 2021 第一轮省赛 A 组 F 题(B 组 G 题)。

解题思路:


dp,一共有四种情况:1正好一个砝码

2不加砝码

3加一个砝码

4减一个砝码

完整代码如下:


#include <bits/stdc++.h>

using namespace std;

const int maxn=1e5+5;

int w[101],f[101][maxn];

int main()

{

int n,sum=0,t=0;

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]) f[i][j]=1; //正好一个砝码

else if(f[i-1][j]) f[i][j]=1;//不变

else if(f[i-1][j+w[i]]) f[i][j]=1;//加一个

else if(f[i-1][abs(j-w[i])]) f[i][j]=1;//减一个

}

}

for(int i=1; i<=sum; i++) if(f[n][i]) t++;

cout<<t;

return 0;

}

遗址


题目描述


很久很久以前有一座寺庙,从上往下看寺庙的形状正好是一个正方形,由 4 个角上竖立的圆柱搭建而成。现在圆柱都倒塌了,只在地上留下圆形的痕迹,可是现在地上有很多这样的痕迹,专家说一定是最大的那个。

写一个程序,给出圆柱的坐标,找出由 4 个圆柱构成的最大的正方形,因为这就是寺庙的位置,要求计算出最大的面积。注意正方形的边不一定平行于坐标轴。

例如图有 10 根柱子,其中 (4,2),(5,2),(5,3),(4,3) 可以形成一个正方形,(1,1),(4,0),(5,3),(2,4) 也可以,后者是其中最大的,面积为 10。

输入格式


第一行包含一个 N(1<= N<= 3000),表示柱子的数量。

接下来 N 行,每行有两个空格隔开的整数表示柱子的坐标(坐标值在 0 到 5000 之间),柱子的位置互不相同。

输出格式


如果存在正方形,输出最大的面积,否则输出 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% 满足:1<=N <=100。

60% 满足:1<= N <=500。

100%满足:1<= N <=3000。

解题思路:


可以用两个点来求出另外两个点,使之四个点成为一个正方形,再判断另外两个点是否存在

完整代码如下:


#include <bits/stdc++.h>

using namespace std;

const int maxn=5005;

int f[maxn][maxn];//存储存在的点

struct point{

int x,y;

}p[maxn];

int main()

{

int n;

cin>>n;

for(int i=1; i<=n; i++) {

cin>>p[i].x>>p[i].y;

f[p[i].x][p[i].y]=1;

}

int a,b,ax,ay,bx,by,sum=0;

for(int i=1; i<=n; i++){

for(int j=1; j<=n; j++){

a=p[i].x-p[j].x;

b=p[i].y-p[j].y;

ax=p[i].x+b;

ay=p[i].y-a;

bx=p[j].x+b;

by=p[j].y-a;

//求出另外两个点

if(ax<1 || ax>5000 || bx<1 || bx>5000 || ay<1 || ay>5000 || by<1 || by>5000) continue;

if(f[ax][ay] && f[bx][by]){

sum=max(sum,a*a+b*b);

}

}

}

cout<<sum;

return 0;

}

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


题目描述


LQ 国拥有 n 个城市,从 0 到 n - 1 编号,这 n 个城市两两之间都有且仅有一条双向道路连接,这意味着任意两个城市之间都是可达的。每条道路都有一个属性 D,表示这条道路的灰尘度。当从一个城市 A 前往另一个城市 B 时,可能存在多条路线,每条路线的灰尘度定义为这条路线所经过的所有道路的灰尘度之和,LQ 国的人都很讨厌灰尘,所以他们总会优先选择灰尘度最小的路线。

LQ 国很看重居民的出行环境,他们用一个指标 P 来衡量 LQ 国的出行环境,P 定义为:

其中 d(i,j) 表示城市 i 到城市 j 之间灰尘度最小的路线对应的灰尘度的值。

为了改善出行环境,每个城市都要有所作为,当某个城市进行道路改善时,会将与这个城市直接相连的所有道路的灰尘度都减少 1,但每条道路都有一个灰尘度的下限值 L,当灰尘度达到道路的下限值时,无论再怎么改善,道路的灰尘度也不会再减小了。

具体的计划是这样的:

  • 第 1 天,0 号城市对与其直接相连的道路环境进行改善;

  • 第 2 天,1 号城市对与其直接相连的道路环境进行改善;

……

  • 第 n 天,n - 1 号城市对与其直接相连的道路环境进行改善;

  • 第 n + 1 天,0 号城市对与其直接相连的道路环境进行改善;

  • 第 n + 2 天,1 号城市对与其直接相连的道路环境进行改善;

……

LQ 国想要使得 P 指标满足 P <= Q。请问最少要经过多少天之后,P 指标可以满足 P <= Q。如果在初始时就已经满足条件,则输出 0;如果永远不可能满足,则输出 -1。

输入格式


输入的第一行包含两个整数 n, Q,用一个空格分隔,分别表示城市个数和期望达到的 P 指标。

接下来 n 行,每行包含 n 个整数,相邻两个整数之间用一个空格分隔,其中第 i 行第 j 列的值 D{i,j} (D{i,j}=D{j,i},D{i,i} = 0) 表示城市 i 与城市 j 之间直接相连的那条道路的灰尘度。

接下来 n 行,每行包含 n 个整数,相邻两个整数之间用一个空格分隔,其中第 i 行第 j 列的值 L{i,j} (L{i,j} = L{j,i}, L{i,i} = 0) 表示城市 i 与城市 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(1, 0) = 2, d(1, 1) = 0, d(1, 2) = 1;

  • d(2, 0) = 3, d(2, 1) = 1, d(2, 2) = 0。

初始时的 P 指标为 (2 + 3 + 1) * 2 = 12,不满足 P <= Q = 10;

第一天,0 号城市进行道路改善,改善后的图示如下:

注意到边 (0, 2) 的值减小了 1,但 (0, 1) 并没有减小,因为 L_{0,1} = 2 ,所以 (0, 1) 的值不可以再减小了。此时每对顶点之间的灰尘度最小的路线对应的灰尘度为:

  • 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(2, 0) = 3, d(2, 1) = 1, d(2, 2) = 0。

此时 P 仍为 12。

第二天,1 号城市进行道路改善,改善后的图示如下:

此时每对顶点之间的灰尘度最小的路线对应的灰尘度为:

  • 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(2, 0) = 2, d(2, 1) = 0, d(2, 2) = 0。

此时的 P指标为 (2 + 2) * 2 = 8 < Q,此时已经满足条件。

所以答案是 2。

【评测用例规模与约定】

  • 对于 30% 的评测用例,1 <=n <= 10,0 <= L{i,j} <= D{i,j} <=10;

  • 对于 60% 的评测用例,1 <= n <= 50,0 <= L{i,j} <=D{i,j} <=10^5;

  • 对于所有评测用例,1 <= n <=100,0 <= L{i,j} <= D{i,j} <= 10^5,0 <= Q <= 2^31 - 1。

蓝桥杯 2022 国赛 A 组 F 题。

解题思路:


用floyd求最短路,用二分法寻找最小天数

完整代码如下:


#include <bits/stdc++.h>

using namespace std;

# define N 105

long long n,q,edge[N][N],m_edge[N][N],dis[N][N],down[N][N];

int check(long long day);

int main()

{

cin>>n>>q;

for(int i=1; i<=n; i++){

for(int j=1; j<=n; j++){

cin>>edge[i][j];

}

}//存图

for(int i=1; i<=n; i++){

for(int j=1; j<=n; j++){

cin>>m_edge[i][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(edge[i][j],edge[i][k]+edge[k][j]);

}

}

}//floyd求最短路;

long long p;

for(int i=1; i<=n; i++){

for(int j=1; j<=n; j++){

p+=dis[i][j];

}

}

if(p<=q){

cout<<"0";

return 0;

}//一开始就满足

long long mid,l=1,r=1e9+5,sum;

while(l<=r){

mid=(l+r)/2;

if(check(mid)){

sum=mid;

r=mid-1;

}else l=mid+1;

}//二分查找

if(l==1e9+5) cout<<"-1";

else cout<<sum;

return 0;

}

int check(long long day)

{

long long ans=0;

for(int i=1; i<=n; i++){

for(int j=1; j<=n; j++){

down[i][j]=0;

}

}//初始化每条道路减少的灰尘量

if(day<=n){

for(int i=1; i<=day; i++){

for(int j=1; j<=n; j++){

down[i][j]=1;

}

}

}else{

int m=day/n;

day=day%n;

for(int i=1; i<=n; i++){

for(int j=1; j<=n; j++){

down[i][j]=m;

}

}

for(int i=1; i<=day; i++){

for(int j=1; j<=n; j++){

down[i][j]++;

}

}

}//计算当前天数下,每条道路能减少的灰尘度

for(int i=1; i<=n; i++){

for(int j=1; j<=n; j++){

dis[i][j]=max(edge[i][j]-down[i][j],m_edge[i][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]);

}

}

}//floyd求最短路;

for(int i=1; i<=n; i++){

for(int j=1; j<=n; j++){

ans+=dis[i][j];

}

}

if(ans<=q) return 1;

else return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值