HBCPC2021-河北省大学生程序设计竞赛-部分题解

7-1 理财

签到题,用scanf和printf进行格式输出更简单
AC代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    double n,x,y;
    scanf("%lf %lf %lf",&n,&x,&y);
    double ans=((n/x)*y)-n;
    printf("%.4f",ans);
    return 0;
}

7-2 B-棋盘

原本以为很难,然后抱着试一试的心态,找了找规律,感觉这个规律是没有问题的,就写代码了,主要是题目中的棋盘格子是没有障碍物的,每个格子都能走,发现能按照S型路线走,就能有路径,不能按照S型走就一定不存在经过每个格子的路径
在草稿纸上列举了几个棋盘样式分析了一下
在这里插入图片描述
AC代码:

#include<iostream> 
#include<stdio.h>
using namespace std;
int n,m;
int main()
{
	cin>>n>>m;
	if(n%2==0&&m%2==0)  //一定不存在路径
	{
		printf("NO");
		return 0;
	} 
	printf("YES\n");
	if(n%2)  //行为奇数
	{
		for(int i=1;i<=n;i++)
		{
			if(i%2) 
			{
				for(int j=1;j<=m;j++)
				{
					if(i==1&&j==1) continue;
					if(i==n&&j==m) break;
					printf("%d %d\n",i,j);	
				}
			} 
			else
			{
				for(int j=m;j>=1;j--)
				{
					printf("%d %d\n",i,j);	
				}
			}
			
		}
	} 
	else //列为奇数
	{
		for(int j=1;j<=m;j++)
		{
			if(j%2)
			{
				for(int i=1;i<=n;i++)
				{
					if(i==1&&j==1) continue;
					if(i==n&&j==m) break;
					printf("%d %d\n",i,j);	
				}
			}
			else
			{
				for(int i=n;i>=1;i--)
				{
					printf("%d %d\n",i,j);	
				}
			}
		}
	} 
	return 0;
}

7-5 E-求导

  1. 模拟即可,多项式每一项的形式只会是A、x、Ax、x^i、Ax ^i 五种情况的一个
  2. 注意系数和次数不是只为个位数,与字符串的一个字符是不对应的,需要进行字符串分割
  3. 注意数据范围要开long long,本来以为不用,但是后来发现怎么都过不了,开了以后就过了
    AC代码;
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
string in;
int main()
{
	getline(cin,in);
	in+="+";
	char a;
	string sa="";
	string pre="";   //前一个+-号
	cout<<"f'(x)=";
	LL len=in.length();
	LL i=5;
	if(in[i]=='-') 
	{
		i=6; pre="-";
	}
	for(;i<len;i++)
	{
	    a=in[i];
	    if(a=='+'||a=='-')   //对前面一项求导
        {
            if(sa.length()==1&&sa=="x")  //只有一个x
            {
                cout<<pre<<1;
            }
            else if(sa.find('x')==-1)    //只有一个A
            {
            	if(sa.length()+6+pre.length()==len)  cout<<0;  //只有一项 
            }
            else if(sa[sa.length()-1]=='x')  //Ax的情况
            {
            	string num=sa.substr(0,sa.length()-1);
            	LL t=atoi(num.c_str());
                cout<<pre<<t;
            }
            else if(sa[0]=='x')  //x^i的情况
            {
            	string num=sa.substr(2,sa.length()-2);
            	LL mi=atoi(num.c_str());
                if(mi==2) cout<<pre<<"2x";
                else cout<<pre<<mi<<"x^"<<mi-1;
            }
            else      //Ax^i的情况
            {
            	LL index=sa.find('x');
            	string Ai=sa.substr(0,index);
            	LL A=atoi(Ai.c_str());
            	string ii=sa.substr(index+2,sa.length()-index-2);
                LL mi=atoi(ii.c_str());
                if(mi==2) cout<<pre<<A*mi<<'x';
                else cout<<pre<<A*mi<<"x^"<<mi-1;
            } 
            sa="";
            pre=a;
        }
        else sa+=a;
	}
	return 0; 
} 

7-8 H-信号传输

  1. 0/1背包的变题,一看就知道大概是dp的问题,看时间复杂度,只能保持在O(nlogn)下,dp只能是一维的,或者有优化手段
  2. 与0/1背包不同的是,在某个城市判断是否修基站,不修就直接与dp[i-1]的状态一样,要修就需要从前一个基站转移而来,前一个基站距离当前的基站是多少并不知道,0/1背包中,前一个选择的物品距离当前判断的物品的距离是i-v[i],因此需要枚举这个距离
  3. 如果是普通的暴力枚举,O(n^2)的时间复杂度,会超时,观察发现满意度和任意基站间的最小距离是有线性关系的,最小距离越大,也就是基站修得越多,满意度就会越少,因此可以二分枚举最小距离来进行求解,时间复杂度为O(nlogn)
    在这里插入图片描述
    AC代码:
#include<iostream>
using namespace std;
const int N=200005;
typedef long long LL;
LL a[N];
LL dp[N];
LL n,w;
int main()
{
    cin>>n>>w;
    for(int i=1;i<=n;i++) cin>>a[i];
    int l=0,r=n+1,x;       //二分任意两个基站间的最小距离 
    while(l<r)
    {
        x=(l+r+1)/2;       //求得任意两个基站间的最小距离 
        dp[0]=0;
        for(int i=1;i<=n;i++)    //第i个城市判断是否修基站 
        {
            dp[i]=dp[i-1];       //第i个城市不修基站,满意度跟前i-1个城市两个基站间最小距离为x的满意度一样 
            if(i-x>=0&&i+x<=n+1)    //想在第i个城市修基站,至少得与两端的基站保持x的距离 
            {
                dp[i]=max(dp[i],dp[i-x]+a[i]);    //在该地方修基站,得到的满意度为距离第i个城市为x的城市转移而来  
            }
        }
        if(dp[n]>=w)    //满意度太多了,基站修太多了,可以适当增大最小距离取值范围 
        {
            l=x;
        }
        else r=x-1;    //满意度太少,基站修得不够,需要减小最小距离的取值范围 
    }
    if(l==0) cout<<-1<<endl;   
    else cout<<l<<endl;
    return 0;
}

7-10 罚时算术

对输入输出做一下简单的处理即可

#include<iostream>
using namespace std;
int n;
int a,b;
int main()
{
    char t;
    cin>>n;
    cin.get(); //吸收掉换行符
    for(int i=0;i<n;i++)
    {
        t=cin.get();    //先读一个看看,然后再放回缓冲区内
        cin.putback(t);
        if(t=='-')
        {
            cin>>a;
            cout<<0<<endl;
        }
        else
        {
            cin>>a>>t>>b;
            cout<<a+b*20<<endl;
        }
        cin.get();  //吸收掉换行符
    }
    return 0;
}
  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值