題目鏈接: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;
}