SDUT_2012省赛选拔赛2 部分题目

http://acm.hdu.edu.cn/vcontest/vtl/problemlist/showproblemlist/vtlid/3367

1009 原来比赛做过的一个题目,由于最近写了几个字典树的题目,所以我对每个姓名编号的时候用字典树写的可是不知道哪里出了错误,老是wa弄得整个比赛的心情一团糟,最后我直接暴枚举力标号,已提交a了。。郁闷啊。。。

思路:输入A找与A有公共朋友最多的B,如果和A有公共朋友最多且相等的话就按字典序输出。。

注意:在找A的后继的后继B时,1:B不能是A本身:2:也不能是A的直接朋友。相当于一个模拟找的过程。。

View Code
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstdlib>
#define maxn 2007
using namespace std;

struct mode
{
int len;
int num[maxn];
}p[maxn];

int pos;
int n,m,hash[maxn];
int L;
char str[maxn][25];

char tt[maxn][25];

int cmp(const void *a,const void *b)
{
return strcmp((char*)a,(char*)b);
}

int getnum(char *ss)
{
for (int i = 0; i < L; ++i)
{
if (!strcmp(str[i],ss))
{
return i;
}
}
strcpy(str[L++],ss);
return L - 1;
}
int main()
{
//freopen("in.txt","r",stdin);
int i,t,cas = 1;
char s1[20],s2[20];
scanf("%d",&t);
while (t--)
{
printf("Case %d:\n",cas++);
L = 0; pos = 0;
memset(hash,0,sizeof(hash));
memset(p,0,sizeof(p));
scanf("%d%d",&n,&m);
for (i = 0; i < n; ++i)
{
scanf("%s%s",s1,s2);
int num1 = getnum(s1);
int num2 = getnum(s2);
p[num1].num[p[num1].len++] = num2;//p.num存放后继元素
p[num2].num[p[num2].len++] = num1;
}
while (m--)
{
memset(hash,0,sizeof(hash));
scanf("%s",s1);
int num3 = getnum(s1);
int M = -9999999;
for (i = 0; i < p[num3].len; ++i)
{
int mm = p[num3].num[i];
for (int j = 0; j < p[mm].len; ++j)
{
int l = p[mm].num[j];
if (l != num3)//l不能是num3本身
{
bool flag = false;
for (int pp = 0; pp < p[num3].len; ++pp)//也不能是num3的直接朋友
{
if (l == p[num3].num[pp])
{
flag = true;
break;
}
}
if (!flag)
{
hash[l]++;
M = max(hash[l],M);//中出拥有公共朋友最多的数目
}
}
}
}
memset(tt,0,sizeof(tt));
int k = 0;
for (i = 0; i < L; ++i)
{
if (hash[i] == M)
{
strcpy(tt[k++],str[i]);
}
}
if (k == 0) printf("-\n");
else
{
qsort(tt,k,sizeof(tt[0]),cmp);
for (i = 0; i < k - 1; ++i)
printf("%s ",tt[i]);
printf("%s\n",tt[k - 1]);
}
}
}
return 0;
}

1006 纯物理题啊。做ACM的人伤不起。。。。

考虑两点:

1:能够到达最高点,最高点一定要比起点高。 

2:sweet到达bitter那点时,速度一定要大于等于bitter的速度,所以根据能量守恒定律(1/2)*m1*v^2 + m1*g*h0  (初始的总能量)= (1/2)*m1*vi^2 + m1*g*hx; (到达这一点且速度比bitter的速度大时最少应该具有的能量) 利用三角形相似求hx

View Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define maxn 1007
using namespace std;

const double g = 20.0;
struct node
{
int x,y;
}p[maxn];

int n;
int main()
{
int i,j,t,m,m1,vt,x,w;;
double v;
int cas = 1;
scanf("%d",&t);
while (t--)
{
memset(p,0,sizeof(p));
scanf("%d%d%d",&n,&m,&m1);
scanf("%d%d",&p[0].x,&p[0].y);
int maxh = p[0].y;
for (i = 1; i < n; ++i)
{
scanf("%d%d",&p[i].x,&p[i].y);
maxh = max(maxh,p[i].y);
}
v = sqrt(2.0*g*(maxh - p[0].y));//找出最大高度
double h0 = p[0].y;
double hx = 0;
for (i = 0; i < m; ++i)
{
scanf("%d%d%d",&x,&vt,&w);
for (j = 0; j < n; ++j)
{
if(x == p[j].x)
{
hx = p[j].y; break;
}
else if (x > p[j].x && x < p[j + 1].x)
{
double hi = (1.0*(p[j + 1].x - x)/(1.0*(p[j + 1].x - p[j].x)))*(p[j + 1].y - p[j].y);//才开始这里1.0*的时候括号没加全,贡献了无数的WA郁闷啊
hx = p[j + 1].y - hi;
break;
}
}
double vx = sqrt(1.0*vt*vt + 2.0*g*(hx - h0));
if (v < vx) v = vx;
}
printf("Case %d: %.2lf\n",cas++,v);
}
return 0;
}


1004 floyd的题目的逆过程。利用floyd可以求出任意两点之间的最短距离,题目相当于给出了floyd之后的图,然后然你检查是否正确,如果正确,原图最少应有几条边?

这里von的思路绝对正确,利用floyd判一遍只要,如果出现map[i][j] > map[i][k] + map[k][j] 肯定会出错,因为经过floyd之后不会再存在这样的边,如果遇到

map[i][j] = map[i][k] + map[k][j]则减去一条边,就是这里的一个小细节卡了我们,使我们贡献了多次WA这里可能存在多个k使map[i][j] = map[i][k] + map[k][j]但是我们删去的只有一条边,所以要判重。。。

View Code
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstdlib>
#define maxn 107
#define inf 9999999
using namespace std;

int map[maxn][maxn];
int n,ans;
bool flag;
bool mark[maxn][maxn];
void floyd()
{
int i,j,k;
for (k = 0; k < n; ++k)
{
if (flag) break;
for (i = 0; i < n; ++i)
{
if (flag) break;
for (j = 0; j < n; ++j)
{
if (i != j && j != k && i != k && map[i][j] != inf && map[i][k] != inf && map[k][j] != inf)
{
if (map[i][j] == map[i][k] + map[k][j] && !mark[i][j])
{
mark[i][j] = true;
ans--;
}
if (map[i][j] > map[i][k] + map[k][j])
{
flag = true;
break;
}
}
}
}
}
}
int main()
{
int i,j,t;
int cas = 1;
scanf("%d",&t);
while (t--)
{
scanf("%d",&n);
memset(mark,false,sizeof(mark));
ans = n*(n-1);
flag = false;
for (i = 0; i < n; ++i)
{
for (j = 0; j < n; ++j)
map[i][j] = inf;
}
for (i = 0; i < n; ++i)
{
for (j = 0; j < n; ++j)
scanf("%d",&map[i][j]);
}
floyd();
if (flag) printf("Case %d: impossible\n",cas++);
else printf("Case %d: %d\n",cas++,ans);
}
return 0;
}

1033 当时是von做的,幸亏是他做,要不我就惨了。赛后做了一下,各种细节上的错误。

1:首先不知到abs,与fabs的区别,一个求整数的绝对值,一个是求小数的绝对值的。

2:对于精度的控制的理解更加深刻了。

3:eps= 1e-8我二逼的给定已成int型了。。调了一个晚上也没找出来。今天才发现。郁闷啊。。

思路很简单就是二分枚举每条可能的边如果能够组成360度,就ok,否则impossible

View Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define maxn 107
using namespace std;

const double pi = 2*acos(-1.0);
const double eps = 1e-8;
int n;
double a[maxn];
//cmp函数的书写更加清晰了
int cmp(double y)
{
if (y > eps) return 1;
else if (y < -eps) return -1;
else return 0;
}
double cal(double c)
{
double sum = 0.0;
for (int i = 0; i < n; ++i)
{
// 首先满足三角形性质
if(cmp(c - (a[i] + a[i + 1])) >= 0) return 1;
if(cmp(fabs(a[i] - a[i + 1]) - c) >= 0) return -1;
double tmp = (a[i]*a[i] + a[i + 1]*a[i + 1] - c*c)/(2.0*a[i]*a[i + 1]);
sum += acos(tmp);
}
if (cmp(sum - pi) > 0) return 1;
else if (cmp(sum - pi) < 0) return -1;
else return 0;
}
int main()
{
//freopen("in.txt","r",stdin);
int i,t,cas = 1;
scanf("%d",&t);
while (t--)
{
scanf("%d",&n);
for (i = 0; i < n; ++i)
{
scanf("%lf",&a[i]);
}
a[n] = a[0];
double l = 0;
double r = 10000;
double m;
bool flag = false;
while (cmp(l - r) < 0)
{
m = (l + r)/2.0;
int tmp = cal(m);
//printf(">>%d\n",tmp);
if (tmp > 0)
r = m;
else if (tmp < 0)
l = m;
else
{
flag = true;
break;
}
}
if (flag)
{
printf("Case %d: %.3lf\n",cas++,m);
}
else
{
printf("Case %d: impossible\n",cas++);
}
}
return 0;
}







你可能感兴趣的:(2012)