快期末了 好久没用过C,重新打一下程设二的内容找找手感,顺便水几篇博客,简单题直接过,需要思考的会有注释或者思路,重要知识点会总结,祝大家期末都AK!!!
总题目链接
3-1养兔子
#include <stdio.h>
#include <stdlib.h>
long long sum[100];
void getfibo()//直接预处理把1-90天都算出来(因为n<=90)
{
sum[1]=1;
sum[2]=2;
for(int i=3;i<=90;i++)
sum[i]=sum[i-1]+sum[i-2];
}
int main()
{
int n;
getfibo();
while(~scanf("%d",&n)&&n)
{
printf("%lld\n",sum[n]);
}
return 0;
}
此题就是一个典型斐波那契数列,如下:
下面兔子都以对为单位,可以看出第n天出生的是由第n-1天成年的和第n-1天新生的兔子(长大一天第n天可以生了)一起生的,而第n-1天出生的又由有第n-2天出生和成年的一起生的……如此递推,很容易得出第i天出生的兔子数:1 1 2 3 5……,同理总兔子数也可以求得为 1 2 3 5 8…即斐波那契数列。
3-2 母牛的故事
思路:
当年数小于等于4的时候,第几年就是有几头牛,当n=5的时候,这时候第一年出生的那个小母牛就也可以生出小母牛了,可得,第n-3年有多少头母牛,到了第n年这些牛都能生小牛了,因此出生数为a[n-3],从而可以得到今年的母牛数为:
a[n] = a[n-1]+a[n-3],
#include <stdio.h>
#include <stdlib.h>
long long a[100];
void getfibo()
{
a[1]=1;
a[2]=2;
a[3]=3;
for(int i=5;i<=55;i++)
a[i]=a[i-1]+a[i-3];
}
int main()
{
int n;
getfibo();
while(~scanf("%d",&n)&&n)
{
printf("%lld\n",a[n]);
}
return 0;
}
3-3鬼吹灯之龙岭迷窟
#include <stdio.h>
#include <stdlib.h>
long long a[100];
void getfibo()
{
a[1]=5;
a[2]=8;
for(int i=3;i<=20;i++)
a[i]=a[i-1]+a[i-2];
}
int main()
{
int n;
getfibo();
while(~scanf("%d",&n)&&n)
{
printf("%lld\n",a[n]);
}
return 0;
}
3-4骨牌铺方格
课本讲的挺详细了,其实也是个斐波那契数列
#include <stdio.h>
#include <stdlib.h>
long long a[100];
void getfibo()
{
a[1]=1;
a[2]=2;
for(int i=3;i<=50;i++)
a[i]=a[i-1]+a[i-2];
}
int main()
{
int n;
getfibo();
while(~scanf("%d",&n)&&n)
{
printf("%lld\n",a[n]);
}
return 0;
}
3-5爬楼梯
巧合的是这题代码和上一题一模一样,因为本质也是骨牌铺方格。
因为一次只能走1级或2级,当n>2时,要走到第n级,那么前一步肯定是走1级或者2级,所以走到第n级的方法次数就是a[n-1]+a[n-2]。
#include <stdio.h>
#include <stdlib.h>
long long a[100];
void getfibo()
{
a[1]=1;
a[2]=2;
for(int i=3;i<=50;i++)
a[i]=a[i-1]+a[i-2];
}
int main()
{
int n;
getfibo();
while(~scanf("%d",&n)&&n)
{
printf("%lld\n",a[n]);
}
return 0;
}
3-6三国佚事——巴蜀之危
书上讲的很明白啦
#include <stdio.h>
#include <stdlib.h>
long long a[100];
void getfibo()
{
a[1]=0;
a[2]=1;
for(int i=3;i<=20;i++)
a[i]=(i-1)*(a[i-1]+a[i-2]);
}
int main()
{
int n;
getfibo();
while(~scanf("%d",&n))
{
printf("%lld\n",a[n]);
}
return 0;
}
3-7王小二切饼
思路
第n刀最多能和前面的n-1条线全部相交产生n个交点,划过n个面,所以能新增n个,加上原来的即a[n-1],得递推:a[n]=n+a[n-1];
#include <stdio.h>
#include <stdlib.h>
long long a[100];
void getfibo()
{
a[1]=2;
for(int i=2;i<=100;i++)
a[i]=a[i-1]+i;
}
int main()
{
int n;
getfibo();
while(~scanf("%d",&n))
{
printf("%lld\n",a[n]);
}
return 0;
}
3-8 C语言实验——拍皮球
#include <stdio.h>
#include <stdlib.h>
int main() {
double h, n;
scanf("%lf %lf", &h, &n);
double ans = h;
n--;
h /= 2;
while (n--) {
ans += h * 2;
h /= 2.0;
}
printf("%.2f %.2f\n", ans, h);
return 0;
}
3-9蟠桃记
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
while(~scanf("%d",&n)&&n)
{
n--;
int ans=1;
while(n--)
{
ans=(ans+1)*2;
}
printf("%d\n",ans);
}
return 0;
}
3-10马拦过河卒
1.递推做法
其实可以类比上面题目的走楼梯,要走到(x,y)有两种方式,即从左边和从上面走过来,容易得到递推式,写出代码,要注意的是边界判断和马的判断。
#include<stdio.h>
int main()
{
int dx[9]={0,-2,-1,1,2,2,1,-1,-2};
int dy[9]={0,1,2,2,1,-1,-2,-2,-1};
int m , n , x, y,i , j ;
long long int f[20][20]={0};
int g[20][20]={0};
scanf("%d %d %d %d",&n,&m,&x,&y);
g[x][y]=1;
for(i=1;i<=8;i++)
if(x+dx[i]>=0&&x+dx[i]<=n&&y+dy[i]>=0&&y+dy[i]<=m)
g[x+dx[i]][y+dy[i]]=1;
for(i=1;i<=n;i++)
{
if(g[i][0]!=1)
f[i][0]=1;
else
for(;i<=n;i++)
{
f[i][0]=0;
}
}
for(j=1;j<=m;j++)
{
if(g[0][j]!=1)
f[0][j]=1;
else
for(;j<=m;j++)
f[0][j]=0;
}
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(g[i][j]==1)
f[i][j]=0;
else
f[i][j]=f[i-1][j]+f[i][j-1];
}
}
printf("%lld\n",f[n][m]);
return 0;
}
2.DFS&BFS
学完图论后会学到dfs和bfs,感兴趣可以研究,不展开讨论
#include<bits/stdc++.h>
using namespace std;
int mmp[100][100] ;//棋盘
int vis[100][100] ; //标记变量
int step = 0 ; //记录路径数
int a ,b ,n , m ;
int next1[9][2]={0,0,-2,1,2,1,-2,-1,2,-1,1,2,1,-2,-1,-2,-1,2}; //马的走动方式
void dfs(int x , int y)
{
int i ;
int next[2][2] = {{0,1},{1,0}} ; //卒的走动方式,卒无法向上走,也无法向右走
int tx ,ty ;
if(x==n&&y==m)
step++ ;
for(i=0;i<2;i++)
{
tx = x + next[i][1] ;
ty = y + next[i][0] ;
if(tx<0 || tx>n || ty < 0 || ty > m)
continue ;
if(!vis[tx][ty]&&mmp[tx][ty])
{
vis[tx][ty] = 1 ;
dfs(tx,ty) ;
vis[tx][ty] = 0 ;
}
}
}
int main()
{
int i ;
cin>>n>>m>>a>>b ; //a,b是马的坐标。
memset(vis,0,sizeof(vis)) ;
memset(mmp,1,sizeof(mmp)) ; //先假设棋盘上没有马
for(i=0;i<=8;i++)
{
if(a+next1[i][0]>=0&&a+next1[i][0]<=n&&b+next1[i][1]>=0&&b+next1[i][1]<=m)
{
mmp[a+next1[i][0]][b+next1[i][1]] = 0 ; //马的阻挡,卒无法通过。
}
}
vis[0][0] = 1 ;
dfs(0,0) ;
cout<<step<<endl ;
return 0 ;
}
小结
递推本质就是找规律,需要运用思维,只能靠多练多体会多理解(当然期末考试背背规律也能应付过去)