6 1前考试

过程:

  总体来说今天的结果考试我个人还是比较满意的,该拿的分都拿到了,但过程很艰辛很曲折。我开始看第一题是十分懵逼的,题目描述的是啥都不知道,因此我就先果断放弃了第一题。看完第二题在纸上列了一下等式,移了一下项就会做了,大概花了十几二十分钟就把程序写好了。写完后看了第三题第一个就想画图,结果画了半天越画越乱——so我有回头看第一题。不管三七二十一先花了一些时间打了一个暴力。打完貌似还有很多时间,我就又去画第三题的图。画了半个多小时还是没画出来让我火死了,so我又去调第一题。我开始看第一题的打表,看了大概10分钟多,终于找出了规律。调好后就又回去死磕第三题画图。磕了我n久突然灵光一闪想到了不用画图,就可以想出来,于是开始写代码。之后就开始磕BFS的第四题。

第一题:

一个正整数n,存在多少个x,使得x在十进制下的每一位之和加上x等于n。(1<=n<=10^9)

本来我是从1枚举到n,后来经过大量枚举(跑了n久)发现x的每一位之和不会大于81(9*9),so  x至少大于(n-81),所以不需要从1~n枚举,只需要从n-100枚举到n

#include<bits/stdc++.h>
using namespace std;
int n,a,ans=0,l=0;
int k[1100];
int main()
{
	freopen("num.in","r",stdin);
	freopen("num.out","w",stdout);
	cin>>n;
	for(int i=max(1,n-1100);i<n;i++)//各个位上的数和定<81 (-1100是保险起见)
	{
		a=i; ans=i;
		while(a>0)
		{
			if(ans>n) break;
			ans+=a%10;
			a/=10;
		}
		if(ans==n)
		 l++,k[l]=i;
	}
	cout<<l<<endl;
	for(int i=1;i<=l;i++)
	 cout<<k[i]<<endl;
	return 0;
}

 第二题:

买第一个物品需要花费A元,买第二个物品则需要B元,一起买两个物品需要C元,商品的利润都是相同的成本为a,b元,

则A-a=B-b=C-a-b。 给出A,B,C求出利润

∵ A-a=B-b=C-a-b

∴ A-a+a+b=B-b+a+b=C-a-b+a+b

∴ A+b=B+a=C

∴ a=C-B,b=C-A

#include<bits/stdc++.h>
using namespace std;
int t;
int A,B,C,a;
int main()
{
	freopen("combo.in","r",stdin);
	freopen("combo.out","w",stdout);
	cin>>t;
	for(int i=1;i<=t;i++)
	{
		cin>>A>>B>>C;
		a=C-B;
		cout<<A-a<<endl;
	}
	return 0;
}

第三题:

 积木图可以抽象为一个n*m的网格图,其中第(i,j)的位置有A[i][j]个积木,求表面积。

这题我第一反应就是画图,第二反应也是画图,第三反应还是画图。我画了n久,耗了n久的时间……ヽ(´ー`)ノ(其实这也不能太怪我,毕竟题目描述上有两个图)

现在我灵光一闪,我们来来看看输入样例

把每个数想成一个长方体,先计算出每个长方体的表面积,再计算出每个重叠的面积最后减去重叠的面积即可。

#include<bits/stdc++.h>
using namespace std;
int n,m,sum=0,x,l,r,u,d;
int a[110][110];
int main()
{
	freopen("surface.in","r",stdin);
	freopen("surface.out","w",stdout);
	memset(a,0,sizeof(a));
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	 for(int j=1;j<=m;j++)
	  cin>>a[i][j],sum+=4*a[i][j]+2;
	if(n==1 && m==1 && a[1][1]==1) 
	{
		cout<<sum<<endl; return 0; 
	}
	for(int i=1;i<=n;i++)
	 for(int j=1;j<=m;j++)
	 {
	 	x=a[i][j]; 
		l=a[i][j-1]; r=a[i][j+1];
		u=a[i-1][j]; d=a[i+1][j];
	 	sum-=min(x,l)+min(x,r)+min(x,u)+min(x,d);
	 }
	cout<<sum<<endl;
}

第四题:

给定一个n*n的棋盘,行和列标号为0,1,2,….,n-1。在棋盘的(i_start,j_start)位置上有一位红皇后,每次红皇后可以往六个方向走, 现在红皇后想去(i_end,j_end)点,求最短距离,并且输出一条路径。 显然最短路径有无穷条,请按照以下顺序来搜索:UL, UR, R, LR, LL, L  如果无解,输出Impossible

  

考试时我看出这是bfs,但我表示我不太会打bfs啊!!!

倒着做bfs,每次记一个前驱,从终点倒着搜回去BFS时先把终点加入队列,然后进行拓展枚举6个方向x点到终点的最短距离,再开一个数组pre[x]pre[x]存的是6个方向的其中一个,表示在dis[x]最小的情况下,接下来走哪个方向,输出时递归

#include<bits/stdc++.h>
using namespace std;
int n;
int sx,sy,ex,ey;
int vis[500][500],dis[500][500];
int dx[10]={-2,-2,0,2,2,0};
int dy[10]={-1,1,2,1,-1,-2};
string a[8]={"UL","UR","R","LR","LL","L"};
struct o
{
	int x,y;
}g[500][500],p,pp;
queue<o> d;
void bfs()
{
	for(int i=0;i<=n+100;i++)
	 for(int j=0;j<=n+100;j++)
	  dis[i][j]=500000000;
	dis[sx][sy]=0; vis[sx][sy]=0;
	p.x=sx; p.y=sy;
	d.push(p);
	while(!d.empty())
	{
		p=d.front();
		d.pop();
		vis[p.x][p.y]=0;
		for(int i=0;i<6;i++)
		{
			pp.x=p.x+dx[i]; pp.y=p.y+dy[i];
			if(pp.x<0 || pp.x>=n || pp.y>=n || pp.y<0)
			 continue;
			if(dis[p.x][p.y]+1<dis[pp.x][pp.y])
			{
				dis[pp.x][pp.y]=dis[p.x][p.y]+1;
				g[pp.x][pp.y].x=p.x;
				g[pp.x][pp.y].y=p.y;
				if(!vis[pp.x][pp.y])
				{
					vis[pp.x][pp.y]=1;
					d.push(pp);
				}
			}
		}
	}
}
void anss(int rx,int ry,int lx,int ly)
{
	if(rx==0 && ry==0) return ;
	anss(g[rx][ry].x,g[rx][ry].y,rx,ry);
	for(int i=0;i<6;i++)
	 if(rx+dx[i]==lx && ry+dy[i]==ly)
	 {
	 	cout<<a[i]<<' ';
	 	break;
	 }
	return ;
}
int main()
{
	freopen("redqueen.in","r",stdin);
	freopen("redqueen.out","w",stdout);
	cin>>n>>sx>>sy>>ex>>ey;
	bfs();
	if(dis[ex][ey]==500000000)
	 printf("Impossible\n");
	else
	{
		printf("%d\n",dis[ex][ey]);
		anss(ex,ey,0,0);
	}
	return 0;
}

第四题:

有一个长度为n的序列A,其中A[1]=1,A[n]=x,A[2…n-1]可以是1至k间任意一个正整数。求有多少个不同的序列,使得相邻两个数不同

#include<bits/stdc++.h>
using namespace std;
int n,k,x;
long long m=1000000007;
long long f[110000],l[110000];
//f[i]表示第i个数是x的方案数
//l[i]表示前i个数中a[1]=1的方案数 
int main()
{
	freopen("construct.in","r",stdin);
	freopen("construct.out","w",stdout);
	cin>>n>>k>>x;
	f[2]=k-1;
	for(int i=3;i<n;i++)
	 f[i]=f[i-1]*(k-1)%m;
	 //相邻两个不能相同,因此f[i]的位置不能填f[i-1]位置上的数字
	if(x==1) l[2]=0;
	//相邻两数不相等,而f[1]必须是1,因此x==1时l[2]为0,否则就有一种情况 
	else l[2]=1;
	for(int i=3;i<=n;i++)
	 l[i]=(f[i-1]-l[i-1]+m)%m;
//前i-1个数共有l[i-1]种方案,而i-1的位置是x的有l[i-1],又因为相邻两数不能相等,因此要减去
	cout<<l[n]<<endl;
	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值