“美登杯”上海市高校大学生程序设计邀请赛 (华东理工大学) - B. 小花梨的三角形

问题:
https://acm.ecnu.edu.cn/contest/173/problem/B/
算一下时间复杂度100层的三角形,边长为1的个数,是1+3+5+7+……+199,等差数列求和,是20000个,然后我们知道边长大于1的三角形个数都是要小于边长为1的三角形个数的,粗略地算一下,我们就知道2e4*100 = 2e6,然后我们就可以愉快地暴力了。
但是我们记录不同的时候,我们可以对它进行排序,这样不同顺序但相同字符集的集合就不会重复了。我们可以让 (minchar-‘a’)*10000,然后 (midchar-‘a’)*100,然后( biggestchar - ‘a’*1 ,这样它们就被分在不同的段上了,然后相加之后就不会出现重复的情况,如果直接相加是会有重复的哦,这样就实现了查重。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 105;
char map[maxn][maxn];
int vis[10000000];
int n;
int len;
int cnt = 0;
int tmp[5];

int main()
{
   scanf("%d", &n);
   for (int i=0; i<=n; i++)
   {
   	scanf("%s", map[i]);
   }
   
   for (len=1; len<=n; len++)
   {	
   	for (int i=0; i<=n; i++)
   	{
   		if (i+len>n)
   		{
   			continue;
   		}
   			
   		for (int j=0; j<=i; j++)
   		{
   			if (j+len<=i)
   			{
   				//printf("(%d, %d) (%d, %d) (%d, %d)\n", i, j, i, j+len, i+len, j+len);
   				tmp[0] = map[i][j]-'a';
   				tmp[1] = map[i][j+len]-'a';
   				tmp[2] = map[i+len][j+len]-'a';
   				sort(tmp,tmp+3);
   				//printf("%d %d %d\n", tmp[0], tmp[1], tmp[2]);
   				if (!vis[tmp[0]*10000+tmp[1]*100+tmp[2]])
   				{
   					//printf("%d\n", tmp[0]*10000+tmp[1]*100+tmp[2]);
   					vis[tmp[0]*10000+tmp[1]*100+tmp[2]] = 1;
   					cnt++;
   				}
   			}
   			if (j+len<=i+len)
   			{
   				//printf("(%d, %d) (%d, %d) (%d, %d)\n", i, j, i+len, j, i+len, j+len);
   				tmp[0] = map[i][j]-'a';
   				tmp[1] = map[i+len][j]-'a';
   				tmp[2] = map[i+len][j+len]-'a';
   				sort(tmp,tmp+3);

   				//printf("%d %d %d\n", tmp[0], tmp[1], tmp[2]);

   				if (!vis[tmp[0]*10000+tmp[1]*100+tmp[2]])
   				{
   					//printf("%d\n", tmp[0]*10000+tmp[1]*100+tmp[2]);
   					vis[tmp[0]*10000+tmp[1]*100+tmp[2]] = 1;
   					cnt++;
   				}
   				
   			}
   		}
   	}	
   }
   
   printf("%d\n", cnt);
   return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值