重新思考我们这个程序,可以发现:
1 我们做的第一轮刷选函数search,其实没什么意义
直接放到在searchrect中同时处理就好了
程序没有对searchrect进行优化
2 程序有两个假设量MAXBASE、MARGIN
这两个假设量并没有得到证明
引入这两个假设量不但影响我们的判断速度和准确性
还说明了我们的算法是不完备的
所以 针对1、2做了优化,写了一个完备的算法
目前代码仍计算不出11阶,不过速度提高了一些
另外代码有很多可以优化的地方
并且可以很容易优化为同时扫描各阶,并不增加时间复杂度。
见源代码:
#include
<
stdio.h
>
#include < math.h >
#include < time.h >
#include < assert.h >
const RANK = 10 ; // 针对的阶数
const MINWIDTH = RANK * 2 - 1 ; // 最小宽度
const MAXWIDTH = 200 ; // 最大宽度
int width; // 宽,长方形的宽(且宽大于高)
int maxw; // 最大的正方形
int count = 0 ; // 穷举记数
int minsum; // minsum动态调整(根据现有数据)
int flag[MAXWIDTH]; // 代表被使用的顺序号(索引);下标[1,maxw]为宽度,值[0,RANK-1],>MAXWIDTH做标记用于输出结果,例:flag[maxw]=0,表示宽度为maxw的正方形(最大的正方形)放第一个
int high[MAXWIDTH]; // 已被填放的高度表,比如9×10的长方形放置一个5×5,则数据为:[5 5 5 5 5 0 0 0 0 0]
// 注意:这两个数组用于递归,每个递归使用退出后需要还原原值
void perfectrect();
bool searchrect( int n, int left); // 判断能否填充
bool check( int n);
int main( int argc, char * argv[])
... {
perfectrect();
printf("Complete! ");
return 0;
}
// 优化,第一行不需要用此函数优化
bool check( int n)
... {
int i;
int times;
int sum;
int tmp;
int ctimes;
//最大和当前面积
sum = maxw*maxw+n*n;
times = 2;
for(i=1; i<maxw; i++)
...{
if(flag[i]<MAXWIDTH)
#include < math.h >
#include < time.h >
#include < assert.h >
const RANK = 10 ; // 针对的阶数
const MINWIDTH = RANK * 2 - 1 ; // 最小宽度
const MAXWIDTH = 200 ; // 最大宽度
int width; // 宽,长方形的宽(且宽大于高)
int maxw; // 最大的正方形
int count = 0 ; // 穷举记数
int minsum; // minsum动态调整(根据现有数据)
int flag[MAXWIDTH]; // 代表被使用的顺序号(索引);下标[1,maxw]为宽度,值[0,RANK-1],>MAXWIDTH做标记用于输出结果,例:flag[maxw]=0,表示宽度为maxw的正方形(最大的正方形)放第一个
int high[MAXWIDTH]; // 已被填放的高度表,比如9×10的长方形放置一个5×5,则数据为:[5 5 5 5 5 0 0 0 0 0]
// 注意:这两个数组用于递归,每个递归使用退出后需要还原原值
void perfectrect();
bool searchrect( int n, int left); // 判断能否填充
bool check( int n);
int main( int argc, char * argv[])
... {
perfectrect();
printf("Complete! ");
return 0;
}
// 优化,第一行不需要用此函数优化
bool check( int n)
... {
int i;
int times;
int sum;
int tmp;
int ctimes;
//最大和当前面积
sum = maxw*maxw+n*n;
times = 2;
for(i=1; i<maxw; i++)
...{
if(flag[i]<MAXWIDTH)