题目:
小明最近喜欢搭数字积木。一共有10块积木,每个积木上有一个数字,0~9。
搭积木规则:
每个积木放到其它两个积木的上面,并且一定比下面的两个积木数字小。
最后搭成4层的金字塔形,必须用完所有的积木。
下面是两种合格的搭法:
0
1 2
3 4 5
6 7 8 9
0
3 1
7 5 2
9 8 6 4
请你计算这样的搭法一共有多少种?
思路:
用DFS先求出0-9的全排列放到一维数组里,将一维数组转换成2维数组,如下形式:
0
1 2
3 4 5
6 7 8 9
判断是否符合条件:
seq[i][j] < seq[i +1][j] && seq[i][j] < seq[i + 1][j + 1]
从而求出所有可能取值
答案:768
Code:
//搭积木 768
#include<bits/stdc++.h>
using namespace std;
int row = 4,col;
int seq[5][8];//下标从1开始
int tmp[11];
int cnt = 0;
bool used[10];
void change(){//将一维数组转换成二维数组
int cur = 1;
for(int i = 1; i <= row ; ++i){
for(int j = 1; j <= i; ++j){
seq[i][j] = tmp[cur ++];
}
}
}
bool judge(){//判断二维数组是否符合条件
for(int i = 1; i <= row - 1; ++i){
for(int j = 1; j <= i ; ++j){
if(seq[i][j] > seq[i + 1][j] || seq[i][j] > seq[i + 1][j + 1]) return false;
}
}
return true;
}
int ans = 0;
void dfs(int idx){
//idx:当前要操作的下标(从1开始)
if(idx == 11){
change();
if(judge()){
cnt++;
return ;
}
return ;
}
for(int i = 0; i <= 9; ++i){
if(!used[i]){
tmp[idx] = i;
used[i] = true;
dfs(idx + 1);
used[i] = false;
}
}
}
int main(){
memset(used,false,sizeof(used));
dfs(1);
cout<<cnt<<endl;
return 0;
}
Wrong Aswer:
PS:这道题花了2个多小时(写+ 调试)….心累┓(;´_`)┏……为什么自己写的代码总是出错呢???心累心累心累…..自己真的是太弱了…( Ĭ ^ Ĭ )…
出错的原因在递归那里,我一开始写的是:
//dfs()
for(int i = 0; i <= 9; ++i){
if(!used[i]){
tmp[idx] = i;
used[i] = true;
dfs(idx + 1);
used[i] = false;
tmp[i] = -1;
}
}
是的….在后面复原的时候我写了一行
tmp[i] = -1;
What???
首先,要复原也应该写tmp[idx] = -1;
而且,递归要复原的是给可能选择的值 已经选择过后复原,跟tmp[]数组没有关系啊…