题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=491
////////////////////////////////////////////
此题最简单的算法就是打表,刚开始做的时候直接搜索,减了总数为奇数的情况,但还是TLE
无奈上网搜了下,但大部分都是打表,找了几个没有打表的,把代码粘上仍然是TLE
无奈看了看书,于是又想了想,看了下书,结果看到书上有个这样的题
其思路如下:
对第一行的n个节点分别赋值0 1进行搜索,这个大部分都这样;
用一个二维矩阵p存三角形中每个点的值,当搜索到第i个点的时候,对第1行第i个赋值,然后退出第2行第i-1个,由此推出第3行第i-2个;把结果存到p中;搜索每个点的时候都要记录’+‘出现的次数,记为count;
剪枝主要是当搜索到第i个点的时候 ,如果count>n*(n-1)/4 或者是 i*(i-1)/2-count>n*(n-1)/4 即'+'的个数 或 ‘-’的个数大于三角形中总点数的一半,就退出;如果没有此剪枝,应该不好过;
代码如下:
#include <iostream>
using namespace std;
class Triangle
{
friend int compute(int);
private:
void Backtrack(int t);
int n, //第一行的符号个数
half, //n*(n+1)/4
count, //当前‘+’个数
**p; //幸运三角形矩阵
long sum; //已找到的幸运三角形个数
};
void Triangle::Backtrack(int t)
{
if((count>half)||(t*(t-1)/2-count>half))//当搜索到此层时,如果'+'或’-‘有大于总符号的一半,就退出;
return ;
int i,j;
if(t>n)
sum++;
else
for(i=0;i<2;i++)
{
p[1][t]=i;
count+=i;
for(j=2;j<=t;j++)
{
p[j][t-j+1]=p[j-1][t-j+1]^p[j-1][t-j+2]; //由p[1][t]的值退出t左斜下方的符号;
count+=p[j][t-j+1]; //如果为1 则count++;
}
Backtrack(t+1);
for(j=2;j<=t;j++)
count-=p[j][t-j+1];
count-=i;
}
}
int compute(int n)//计算节点为n的幸运三角形的个数;
{
Triangle x;
x.n=n;
x.count=0;
x.half=n*(n+1)/2;
x.sum=0;
if(x.half%2==1)//如果三角形中总符号数为奇数,则返回0;
return 0;
x.half=x.half/2;
int i,j;
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;
x.p=p;
x.Backtrack(1);
return x.sum;
}
int main()
{
int n;
while(cin>>n)
{
int res=compute(n);
cout<<res<<endl;
}
return 0;
}