week

目录

 1.汤姆猫的天堂梦

题目

输入格式

输出格式

输入输出样例

 题解

代码

2.跑步

题目

输入格式

输出格式

输入输出样例

 题解

代码

3.砝码称重

题目

输入格式

输出格式

输出一个整数代表答案。

输入输出样例

 题解

代码

4.遗址

题目

输出格式

输入输出样例

 题解

代码

5.环境治理

题目

输入格式

输出格式

输入输出样例

题解

代码


 

 1.汤姆猫的天堂梦

题目

汤姆斯生活在一个等级为 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

 题解

简单的dp

代码

#include<bits/stdc++.h>
using namespace std;
int dp[200][200]={0};
int main(){
    int n,a;
    cin>>n;
    for(int i=1;i<=n;++i){
        cin>>a;
        for(int j=1;j<=a;++j){
            dp[i][j]=INT_MAX-1000;
            int b,c;
            cin>>b;
            while(b!=0){
                cin>>c;
                dp[i][j] = dp[i-1][b]+c < dp[i][j] ? dp[i-1][b]+c:dp[i][j];
                cin>>b;
            }
        }
    }
    int min=INT_MAX;
    for(int i=1;i<=a;++i) min=dp[n][i]<min?dp[n][i]:min;
    printf("%d",min);
    return 0;
}

2.跑步

题目

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

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

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

输入格式

一行一个整数,代表 nn。

输出格式

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

输入输出样例

输入 #1复制

212

输出 #1复制

995645335

 题解

使用动态规划最正确,注意dp的数组要开long long 的。

代码

#include<bits/stdc++.h>
using namespace std;
long long n,dp[501];
int main(){
    cin>>n;
    dp[0]=1;
    for (int i=1;i<=n;i++){
    	for (int j=n;j>=i;j--){
    		dp[j] += dp[j-i];
		}
	}
	cout<<dp[n]-1<<endl;
    return 0;
}

3.砝码称重

题目

你有一架天平和 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

 题解

状态方程:

 

代码

#include<bits/stdc++.h>
using namespace std;
const int max1=150000;
int n,sum,w;
bool dp[2][300010];
int main(){
	cin>>n;
	dp[0][max1]=1;
	for(int i=1;i<=n;++i) {
		cin>>w;
		sum += w;
		for(int j=-sum; j<=sum;++j)
			dp[i&1][j+max1] = dp[i-1&1][j-w+max1]||dp[i-1&1][j+w+max1]||dp[i-1&1][j+max1];
	}
	int ans=0;
	for(int i=1;i<=sum;++i) ans += dp[n&1][i+max1];
	printf("%d\n",ans);
	return 0;
}

4.遗址

题目

很久很久以前有一座寺庙,从上往下看寺庙的形状正好是一个正方形,由 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。

 

第一行包含一个 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

 题解

找到正方形的四个顶点,找到两个点 即可确定这个正方形,所以两个for循环确定,最后依次比较即可得出答案。

代码

#include<bits/stdc++.h>
#define max(a,b) a>b?a:b
using namespace std;
bool dp[5020][5020];
int x[3020],y[3020],n,m;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
        scanf("%d%d",x+i,y+i);
        dp[x[i]][y[i]]=1;
	}
	int ans=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			int a=x[i]-x[j];
			int b=y[i]-y[j];
			int Ax=x[i]-b;
			int Bx=x[j]-b;
			int Ay=y[i]+a;
			int By=y[j]+a;
            if(Ax<1||Ax>5000||Bx<1||Bx>5000||Ay<1||Ay>5000||By<1||By>5000)continue;
			if(dp[Ax][Ay] && dp[Bx][By])ans=max(ans,a*a+b*b);
		}
	}
	printf("%d\n",ans);
    return 0;
}

5.环境治理

题目

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−1​j=0∑n−1​d(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

题解

最短路问题,套Floyd模板,加上二分查找,最后得出答案。

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int x[101][101],dis[101][101],diss[101][101], n,m;
int cheak(int k){
	int p=k/n;
	int o=k%n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			diss[i][j]=max(dis[i][j]-p,x[i][j]);
			if(o >= i)diss[i][j]=max(diss[i][j]-1,x[i][j]);
		}
	}
	int ans=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			for(int k=1;k<=n;k++){
				diss[j][k]=min(diss[j][k],diss[j][i]+diss[i][k]);
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			ans+=diss[i][j];
	}
	}
	if(ans<=m)return 1;
	return 0;
}
inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while (ch<'0'||ch>'9'){
            if (ch=='-') f=-1;
            ch=getchar();
    }
	while (ch>='0'&&ch<='9'){
            x=(x<<3)+(x<<1)+ch-48;
            ch=getchar();
    }
	return x*f;
}

signed main(){
	n=read();
	m=read();
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			dis[i][j]=read();
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			x[i][j]=read();
		}
	}
	int p=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			for(int k=1;k<=n;k++){
				dis[j][k]=min(dis[j][k],dis[j][i]+dis[i][k]);
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			p += dis[i][j];
		}
	}
	if(p<=m){
		cout<<"0";
		return 0;
	}
	int l=1,r=1e6;
	while(l<=r){
		int mid=(l+r)>>1;
		if(cheak(mid)==1)r=mid-1;
		else l=mid+1;
	}
	if(l==1e6+1){
		cout<<"-1";
		return 0;
	}
	cout<<l;
	return 0;
}

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值