算法课程设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
<<算法与程序设计>>课程作业
班级:计本08-1班
学号:3081817106
姓名:詹萍
简单算法
符号三角形问题:这个问题用的是回溯法解决的,符号三角形要求在符号三角形的第1行有n个由“+”和“-”组成的符号,以后每行符号比上行少1个,2个同号下面是“+”,2个异号下面是“-”。计算有多少个不同的符号三角形,使其所含“+”和“-”的个数相同。
解题思路:
1、针对所给问题定义解空间,该问题的解空间为n元组x1,x2,x3...xn,其中xi ∈S,S={0,1},其中0代表“+”, 1代表“-”;
2、确定易于搜索的解空间结构,例如子集树,排列树,该问题是子集树;
3、以深度优先原则搜索解空间树,并利用剪枝函数避免无效搜索,这里的约束函数应该为:在符号三角形的第一行的前i个符号x1...xi确定后,就确定了一个由i*(i+1)/2个符号组成的符号三角形。下一步确定了x(i+1)的值后,只要在前面已确定的符号三角形的右边加一条边,就可以扩展为x1...x(i+1)所相应的符号三角形。最终由x1...xn所确定的符号三角形中包含的“+”号个数与“-”号个数同为n*(n+1)/4。因此在回溯搜索过程中可用当前符号三角形所包含的“+”号个数与“-”号个数均不超过n*(n+1)/4作为可行性约束;用0和1代替+和-,执行异或操作推出下一行对应符号,当所有符号总数为奇数时无解,当某种符号超过总数一半时无解。
4.由于回溯法是对解空间的深度优先搜索,不断改变第一行每个符号,搜索符合条件的解,因此可以使用递归回溯。
#include
using namespace std;
class Triangle
{friend int Computer(int);//定义友元函数
private:
void Backtrack(int t); //t,第一行第t个符号
int n, //第1行符号的个数
half, //每个三角形总符号数的一半
count, // 统计减号的个数
**p; //指向三角形的二维指针
long sum; }; //统计符合条件的的三角形的个数
void Triangle::Backtrack(int t)//回溯法
{int i,j,k,s,f;
if((count>half)||(t * (t-1)/2 - count > half))
return; //如果加号或减号的个数大于符号三角形中总符号数的一半则退出函数if(t<=n) //回溯条件直到n
for(i=0; i<2; i++)
{ p[1][t] = i; //第一行第t个符号
count += i; //“-”号统计
for(j=2; j<=t; j++) //当第一行符号>=2时,可以运算出下面行的某些符号
{ p[j][t-j+1] = p[j-1][t-j+1]^p[j-1][t-j+2]; //通过异或运算下行符号
count += p[j][t-j+1];}
if(t>=n)
{ //输出符合条件的三角形
f=0;
for(j=1; j<=t;j++)
for(k=1; k<=t-j+1; k++)
f+=p[j][k];
if(f==half)
{ //如果减号是总符号数的一半则输出并将sum加1
cout<<"第"<<++sum<<"个三角形"<<'\n';
for(j=1; j<=t; j++)
{for(s=1; s for(k=1; k<=t-j+1; k++) { if(p[j][k] == 1) cout<<"- ";//3个空格 else cout<<"+ ";//3个空格} cout<<'\n';} cout<<'\n';}} Backtrack(t+1); //回溯 for(j=2; j<=t; j++) count -= p[j][t-j+1]; count -=i;} } int Computer(int n) //友元函数调用Triangle类的成员函数{ int i,j; Triangle X; X.n = n; X.count = 0; X.sum = 0; X.half = n * (n+1) / 2; if(X.half % 2 == 1) return 0; //如果是一个三角形符号的总数是奇数则不符合条件,返回0 X.half = X.half / 2; int **p = new int * [n+1]; //分配新行 for(i=0; i<=n; i++) p[i] = new int [n+1];//分配新列 for(i=0; i<=n; i++) for(j=0; j<=n; j++) p[i][j] = 0;//给p所指向的二维数组赋值为0 X.p = p; X.Backtrack(1); return X.sum; } void main() { int i, n; cout<<"请输入第一行的符号个数:"; cin>>i; n = Computer(i); cout<<"***************************"<<'\n'; cout<<"共有"< 程序的输入是第一行的符号个数,输出是符合符号三角形的每一种三角形情况,符合符号三角形的总个数。