|
题目:有标号为1,2,3,4的小木块各两块,能不能摆成一列,让两个标号为i的木块中间间隔i个位子,比如,下面是两种可行的摆法
2 3 4 2 1 3 1 4
4 1 3 1 2 4 3 2
此题用dfs来做,第一种做法,枚举1234每个数字可以用两次的有重排列,然后判断排列是否满足条件,在pmn的pr里面加上判断。
怎么判断呢?从左往右找1,位置叫l1,从右往左找1,位置叫r1,那么r1-l1==2(为什么不是1) 4个全判断完。
- #include <iostream>
- using namespace std;
- const int mn=10; ///假设10个
- int a[mn];
- int b[mn];
- int m,n,i;
- void pr()
- {
- ///判断是否符合条件
- int i,l1,l2,l3,l4,r1,r2,r3,r4;
- for (i=1; a[i]!=1; i++);l1=i; ///从左往右找1
- for (i=8; a[i]!=1; i--);r1=i; ///从右往左找1
- for (i=1; a[i]!=2; i++); l2=i;
- for (i=8; a[i]!=2; i--); r2=i;
- for (i=1; a[i]!=3; i++); l3=i;
- for (i=8; a[i]!=3; i--); r3=i;
- for (i=1; a[i]!=4; i++); l4=i;
- for (i=8; a[i]!=4; i--); r4=i;
- bool b=(r1-l1==2);
- b=b&& (r2-l2==3);
- b=b&& (r3-l3==4);
- b=b&& (r4-l4==5);
- if (b)
- {
- for (int j=1; j<=2*n; j++) cout<<a[j];
- cout<<endl;
- }
- }
- void dfs(int i) /// 寻找第i的位置上的数
- {
- if (i>2*n) pr();
- for (int k=1; k<=n; k++)
- if (b[k]>0)
- {
- a[i]=k; /// 选择
- b[k]--; ///标记
- dfs(i+1); ///选下一个
- b[k]++; ///复位
- }
- }
- int main()
- {
- n=4; ///4个木块
- for (int i=1; i<=n; i++) b[i]=2; ///每个2块
- dfs(1); ///从第一个开始
- return 0;
- }
复制代码
这个做法答案是对的但是显然是很浪费的,比如第一个数选1,第二个数还是选了1,此后完全没有必要再去选底3,4,5,6,7,8等位置上的数字,所以很大浪费。我们可以在第一位放1的时候,把第3位也放在1,然后再去选第2位上的数字,假设是2,然后不用选第3位上的数字,(前面决定了已经放了1),直接去选第4位上的数字****
|
|