1.铺砖
题目描述:
对于一个2行N列的走道。现在用12或22的砖去铺满。问有多少种不同的方式(请用递推方式求解)。如果N很大,需要高精度计算。下图是一个2行17列的走道的某种铺法:
输入要求:
一个整数N,N<=1000。
输出要求:
共有多少种铺法。
#include<bits/stdc++.h>
using namespace std;
/*
分为三种情况:
1. 只剩一列,只有一种可能,返回 1
2. 只剩两列,有三种可能,两个 2*1 或一个 2*2
3. 大于等于3,进行递推,pave(n - 1) 代表使用 宽度为1的瓷砖,pave(n - 2)代表使用宽度为2的瓷砖,这种情况有三种可能,但是一种两个1*2竖着排列的可能已包含在1中,所以只剩下两种可能。
*/
long long pave(int n)
{
if (n == 1)
return 1;//一个1*2
else if (n == 2)//1*2 1*2 横竖各一种可能,2*2一种可能
return 3;
else
return pave(n - 1) + 2 * pave(n - 2);//用递归求解,由于1*2 1*2 竖着放和n=1冲突,所以排除了一种。
}
int main()
{
int n;
while (cin >> n)
cout << pave(n) << endl;
return 0;
}
2.装错信封
题目描述:
某人给N个朋友写信,邀请他们来家中聚会。请柬和信封交由助手去处理。粗心的助手却把请柬全装错了信封。请问:助手会有多少种装错的可能呢?
排错公式:
D
(
n
)
=
(
n
−
1
)
[
D
(
n
−
2
)
+
D
(
n
−
1
)
]
D(n) = (n-1)[D(n-2) + D(n-1)]
D(n)=(n−1)[D(n−2)+D(n−1)]
#include<bits/stdc++.h>
using namespace std;
int Fun(int);
int main()
{
int n,res;
cin>>n;
res=Fun(n);
cout<<res<<endl;
return 0;
}
int Fun(int n)
{
if(n==1) return 0;
if(n==2) return 1;
return (n-1)*(Fun(n-1)+Fun(n-2));
}
3.棋盘覆盖
题目描述
在一个2k×2k 个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。
输入要求
输入一个整数k,k<=5;
输入特殊格子的坐标x,y。
输出要求
输出一个由数值表示的二维矩阵。填充规则如下:
(1)用数值填充方格;
(2)特殊方格数值为0;
(3)从中心点开始;然后左上、右上、左下、右下的计数顺序填数;同一块用相同数值表示;
(4)每个数值占4个位置空间;右对齐,左补空格。
输入样例
3
1 2
输出样例
#include<bits/stdc++.h>
using namespace std;
int a[40][40],tile = 1;
void ChessBoard(int tr, int tc, int dr, int dc, int size)
{
//tr:棋盘左上角方格的行号;
//tc:棋盘左上角方格的列号;
//dr:特殊方格所在的行号;
//dc:特殊方格所在的列号。
//每次铺砖后size/2,2*2 铺砖之后size变为1找到特殊方格
if(size == 1) return;
//t 为输入的序号,每次填入L方格后+1
int t = tile++,s = size/2;
//左上、左下、右上、右下的顺序
//tile:L型骨牌号
/*
步骤:
1.判断特殊方格是否在此棋盘中
1.1 不在棋盘中,根据当前方块在特殊方块的什么位置进行填充
1.2 如果在目前棋盘中直接不需要填充,继续棋盘覆盖
2.判断是否结束(size/2 == 1)
2.1 是,结束
2.2 否,返回 1
*/
//覆盖左上角子棋盘
if(dr<tr+s && dc<tc+s)//特殊方格在此棋盘中
ChessBoard(tr,tc,dr,dc,s);//直接覆盖
else
{//方格不在此棋盘中
a[tr+s-1][tc+s-1]=t;//用t覆盖右下
ChessBoard(tr,tc,tr+s-1,tc+s-1,s);//覆盖其余
}
//覆盖右上角子棋盘
if(dr<tr+s && dc>=tc+s)//特殊方格在此棋盘中
ChessBoard(tr,tc+s,dr,dc,s);//直接覆盖
else
{//方格不在此棋盘中
a[tr+s-1][tc+s]=t;//用t覆盖左下
ChessBoard(tr,tc+s,tr+s-1,tc+s,s);//覆盖其余
}
//覆盖左下角子棋盘
if(dr>=tr+s && dc<tc+s)//特殊方格在此棋盘中
ChessBoard(tr+s,tc,dr,dc,s);//直接覆盖
else
{//方格不在此棋盘中
a[tr+s][tc+s-1]=t;//用t覆盖右上
ChessBoard(tr+s,tc,tr+s,tc+s-1,s);//覆盖其余
}
//覆盖右下角子棋盘
if(dr>=tr+s && dc>=tc+s)//特殊方格在此棋盘中
ChessBoard(tr+s,tc+s,dr,dc,s);//直接覆盖
else
{//方格不在此棋盘中
a[tr+s][tc+s]=t;//用t覆盖左上
ChessBoard(tr+s,tc+s,tr+s,tc+s,s);//覆盖其余
}
}
int main()
{
int k,x,y;
// 输入
scanf("%d %d %d", &k, &x, &y);
// 从左上角开始,进行递推,棋盘的大小为 2^k*2^k
ChessBoard(0, 0, x, y, pow(2,k));
// 输出结果
for(int i=0;i<pow(2,k);i++)
{
for(int j=0;j<pow(2,k);j++)
{
printf("%4d",a[i][j]);
}
printf("\n");
}
return 0;
}
4.真币比假币轻
问题描述
找出假币
int find_fake_coin(int* coins, int left, int right)
{
int n = right - left + 1;
if (n == 1)
{ // 如果区间只有一个硬币,它就是假币
return left;
}
int m = n / 2; // 将硬币分成 2 组
int left_sum = 0, right_sum = 0;
for (int i = left; i < left + m; i++)
{ // 计算左、右两组的重量
left_sum += coins[i];
}
for (int i = left + m; i <= right; i++)
{
right_sum += coins[i];
}
if (left_sum == right_sum)
{ // 如果左、右两组的重量相等,则假币在剩余的硬币中
return find_fake_coin(coins, left + m + 1, right);
}
else if (left_sum < right_sum)
{ // 如果左组比右组轻,则假币在左组中
return find_fake_coin(coins, left, left + m - 1);
}
else
{ // 如果左组比右组重,则假币在右组中
return find_fake_coin(coins, left + m, right);
}
}