UVA - 11039 Building designing

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> 题目链接:</span><a target=_blank href="http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34028" style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">UVA - 11039 Building designing</a>


       表示这道题目真的是一段血泪史,如此简单我竟然提交了6次,一开始想复杂了,先将所有数字按照绝对值从小到大排序,然后,然后作死的我居然想到了拓扑排序,在按照绝对值排序后,我们可以这样想,从每个Node[i]向所有满足Node[i]*Node[j]<0(j>i)引一条线,这样一来,题目就变成了一个有向无环图求最长路的问题,然后天杀的我写了一个记忆化搜索,勇敢地提交了,结果错了,但并不是因为我的算法问题,然后我就改,我发现什么记忆化搜索都在扯淡,其实每个Node[i]的后续节点一定是在i之后的第一个符号不同的Node[j],所以并不需要什么记忆化搜索,对于每个节点直接找后续节点就好了,但后来一直错。然后在中午去吃饭的路上,我突然想到了应该是数据溢出了,我用Node[i]*Node[j]<0来判断是否异号。

      改了之后就通过了,然后我改了一下之前那个所谓的记忆化搜索,也过了,不过时间上差好多,全都传上来做个纪念吧。

# include <cstdlib>
# include <cstdio>
# include <algorithm>
# include <cmath>
# include <cstring>
using namespace std;
  
const int size =  500000 + 10;
int num[size];

bool cmp(int a,int b)
{
	return abs(a) < abs(b);
}
int main()
{
	int i,j,k;
    int P;
	scanf("%d",&P);
	while (P--)
	{
		int n;
		scanf("%d",&n);
		for (i=0;i<n;i++)
			scanf("%d",num+i);
		sort(num,num+n,cmp);
		for (i=0;i<n;i++) 
			num[i] = num[i] > 0 ? 1 : -1;/*这部分内容很重要,不这样做后面的乘法会溢出*/
		int ans = 1;
		for (j=i=0;i<n;i++)
			if (num[j]*num[i]<0)
			{
				j = i;
				ans++;
			}
		printf("%d\n",ans);
	}
    return 0;
}

# include <cstdlib>
# include <cstdio>
# include <algorithm>
# include <cmath>
# include <cstring>
using namespace std;
  
const int size =  500000 + 10;
int num[size],dp[size];
int n;

bool cmp(int a,int b)
{
	return abs(a) > abs(b);
}
int getlenth(int x)
{
	if (dp[x]!=-1)
		return dp[x];
	dp[x] = 1;
	for (int i=x+1;i<n;i++)
		if (num[x]*num[i]<0)
		{
			dp[x] = max(dp[x],getlenth(i)+1);
			break;
		}	
	return dp[x];	
}
int main()
{
	int i,j,k;
    int P;
	scanf("%d",&P);
	while (P--)
	{
		memset(dp,-1,sizeof(dp));
		scanf("%d",&n);
		for (i=0;i<n;i++)
			scanf("%d",num+i);
		sort(num,num+n,cmp);
		for(i=0;i<n;i++)
			num[i] = num[i]>0?1:-1;
		int ans = 0;
		for (i=0;i<n;i++)
			ans = max(ans,getlenth(i));
		printf("%d\n",ans);
	}
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值