“美登杯”上海市高校大学生程序设计邀请赛 (华东理工大学)

问题:
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)
", 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
", tmp[0], tmp[1], tmp[2]);
   				if (!vis[tmp[0]*10000+tmp[1]*100+tmp[2]])
   				{
   					//printf("%d
", 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)
", 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
", tmp[0], tmp[1], tmp[2]);

   				if (!vis[tmp[0]*10000+tmp[1]*100+tmp[2]])
   				{
   					//printf("%d
", tmp[0]*10000+tmp[1]*100+tmp[2]);
   					vis[tmp[0]*10000+tmp[1]*100+tmp[2]] = 1;
   					cnt++;
   				}
   				
   			}
   		}
   	}	
   }
   
   printf("%d
", cnt);
   return 0;
}
原文地址:https://www.cnblogs.com/xyqxyq/p/12328899.html