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;
}


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