第四届智慧杯普及组题解

前言

由于疫情原因,今年的智慧杯没有初赛,直接复赛了。
然而我在考试的时候,由于脑子抽风,只得了320分,比预计的少了80分……😩

但是,我还是来写题解啦!😊

第一题:魔法飞毯

大水题,只要学过数组就应该能做。

方法:先从大到小排序,再取前两个的成绩输出。

代码:

#include<bits/stdc++.h>
using namespace std;
bool cmp(int a,int b)
{
	return a>b;
}
int Ar[110000];
int main()
{
	freopen("carpet.in","r",stdin);
	freopen("carpet.out","w",stdout);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&Ar[i]);
	sort(Ar+1,Ar+1+n,cmp);
	long long ans=1LL*Ar[1]*Ar[2];
	printf("%lld",ans);
	return 0;
}

第二题:排球比赛

大模拟,与乒乓球那题有异曲同工之妙。只不过是计分方式不同而已。

代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
	freopen("volleyball.in","r",stdin);
	freopen("volleyball.out","w",stdout); 
	string str;
	cin>>str;
	int Acnt=0,Bcnt=0;
	
	int Competition=1;
	int ALLA=0,ALLB=0;
	for(int i=0;i<str.length();i++)
	{
		if(str[i]=='A')
		{
			Acnt++;
		}else if(str[i]=='B'){
			Bcnt++;
		}else{
			break;
		}
		if(Competition<=4)
		{
			if(Acnt>=25)
			{
				if(Acnt-Bcnt>=2)
				{
					Acnt=0,Bcnt=0;
					ALLA++;
					Competition++;
				}
			}
			if(Bcnt>=25)
			{
				if(Bcnt-Acnt>=2)
				{
					Acnt=0,Bcnt=0;
					ALLB++;
					Competition++;
				}
			}
		}else{
			if(ALLA!=ALLB) break;
			if(Acnt>=15)
			{
				if(Acnt-Bcnt>=2)
				{
					Acnt=0,Bcnt=0;
					ALLA++;
				}
			}
			if(Bcnt>=15)
			{
				if(Bcnt-Acnt>=2)
				{
					Acnt=0,Bcnt=0;
					ALLB++;
				}
			}
		}
	}
	printf("%d:%d",ALLA,ALLB);
	return 0;
}

第三题:巨石阵

就是求下标不连续的和最大的值是多少。
可用dp来做,但本人懒得一匹所以直接用模拟。

(另外,我比赛时用递归,70分……😭)

代码:

#include<bits/stdc++.h>
using namespace std;
int Ans(int Ar[],int len)
{
	int sum1=0,sum2=0;
	for(int i=0;i<len;i++)
	{
		if(i%2==0)
		{
			sum1=max(sum2,sum1+Ar[i]);
		}else{
			sum2=max(sum1,sum2+Ar[i]);
		}
	}
	return max(sum1,sum2);
}
int Ar[1100];
int main()
{
	freopen("stone.in","r",stdin);
	freopen("stone.out","w",stdout);
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++) scanf("%d",&Ar[i]);
	printf("%d",Ans(Ar,n));
	return 0;
}

第四题:二师兄的纪录片

(考试的时候因为没有输出-1+数组开小活生生从100分掉到了50分😭)

先用一种很奇怪的方式求出第i行j列的点的编号:

i*n+j

然后把(i-1)*n+j(i+1)*n+ji*n+(j+1)i*n+(j+1)i*n+j建一条长度为1的双向边。
在可以乘飞机到其他点的位置,两个点之间连一条长度为4的单向边。
与野蛮城市连接的边直接删掉。

最后跑一边已经死了的SPFA,当然,dijkstra、bellman-ford等都行,只要你保证不会TLE(当然不会)

主要问题是存边的数组要大一些,最好是 20010这种大数。

代码:

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
bool vis[250000];
int dis[250000];
int T,N;
struct node
{
    int v,w;
    struct node*next;
}*h[250000];
void LA(int u,int v,int w)
{
    struct node *p=(struct node *)malloc(sizeof(struct node));
    p->v=v;
    p->w=w;
    p->next=h[u];
    h[u]=p;
}
void spfa(int s)
{
    queue<int>Q;
    memset(vis,false,sizeof(vis));
    Q.push(s);
    dis[s]=0;
    while(!Q.empty()){
        int u=Q.front();
        Q.pop();
        vis[u]=false;
        struct node *p;
        for(p=h[u];p!=NULL;p=p->next)
        {
            int q=p->v;
            if(dis[q]>dis[u]+p->w)
            {
                dis[q]=dis[u]+p->w;
                if(!vis[q])
                {
                    vis[q]=true;
                    Q.push(q);
                }
            }
        }
    }
}
int falg[110][110];
int main()
{
	freopen("record.in","r",stdin);
	freopen("record.out","w",stdout);
	int n,p,q;
	scanf("%d%d%d",&n,&p,&q);
    memset(dis,inf,sizeof(dis));
    memset(h,0,sizeof(h));
    for(int i=0;i<p;i++)
    {
    	int x,y;
    	scanf("%d%d",&x,&y);
    	falg[x][y]=1;
	}
    for(int i=0;i<q;i++)
    {
        int x1,x2,y1,y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        LA(x1*n+y1,x2*n+y2,4);
    }
    for(int i=1;i<=n;i++)
    {
    	for(int j=1;j<=n;j++)
    	{
    		int Point=i*n+j;
    		if(i-1>=1 && falg[i-1][j]!=1)
    		{
    			LA(Point,(i-1)*n+j,1);
			}
			if(i+1<=n && falg[i+1][j]!=1)
			{
				LA(Point,(i+1)*n+j,1);
			}
			if(j-1>=1 && falg[i][j-1]!=1)
    		{
    			LA(Point,i*n+(j-1),1);
			}
			if(j+1<=n && falg[i][j+1]!=1)
			{
				LA(Point,i*n+(j+1),1);
			}
		}
	}
    spfa(1*n+1);
    if(dis[n*n+n]==inf)
    {
    	puts("-1");
    	return 0;
	}
    printf("%d\n",dis[n*n+n]+1);
    return 0;
}

最后

最后,我还是要提醒大家:

不开long long见祖宗,
数组开小全RE。

RE与TLE·组歌
血的教训

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值