nyoj 491 幸運三角形

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章