“美登杯”上海市高校大学生程序设计邀请赛 (华东理工大学) - 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;
}