ECUST 09年 校赛个人赛第八场(最后一场)总结
懒惰了,暂时休息一下
这次我只AC了一题(在结束的那一刻,另一题在题目来源地网站上AC了,我们的OJ上仍然WA,我们OJ的Special Judge真是—_—!)
H题是用木棒拼数字,给出木棒数量,要求算出拼出的最大和最小数字
最大数字部分很明显7要用3根棒,1用2根棒,所以如果是奇数就是7+K个1,k=(n-1)/2 -1偶数直接n/2个1
最小数字部分比较麻烦,因为分几种情况,我是DP解决的,也可以找规律,DP的话要注意0和6都是用6根棒,而0不能作为第一个数字
代码如下:
#include<iostream>
using namespace std;
class cal
{
public:
int num[10];
int length;
void Equal(cal a);
bool sThan(cal a);
cal AandB(cal a);
};
cal Num[101];
int main()
{
freopen("h.in","r",stdin);
freopen("h.out","w",stdout);
int i,j;
for(i = 0 ; i < 101 ; i ++)
for(j = 0 ; j < 10 ; j ++)
Num[i].num[j] = 0;
Num[2].num[1] = 1;Num[2].length = 1;
Num[3].num[7] = 1;Num[3].length = 1;
Num[4].num[4] = 1;Num[4].length = 1;
Num[5].num[2] = 1;Num[5].length = 1;
Num[6].num[0] = 1;Num[6].length = 1;
Num[7].num[8] = 1;Num[7].length = 1;
for(i = 8 ; i < 101 ; i ++)
{
Num[i].Equal(Num[2].AandB(Num[i - 2]));
for(j = 3 ; j < 8 && i - j >= 2 ; j ++)
{
if(Num[j].AandB(Num[i - j]).sThan(Num[i]))
Num[i].Equal(Num[j].AandB(Num[i - j]));
}
}
int t;
scanf("%d",&t);
while(t --)
{
int n;
scanf("%d",&n);
if(n == 6)
printf("6 111\n");
else
{
for(i = 1 ; i < 10 ; i ++)
if(Num[n].num[i])
break;
int b1 = i;
printf("%d",b1);
for(i = 0 ; i < 10 ; i ++)
for(j = 0 ; (j < Num[n].num[i] && i != b1)
|| (j < Num[n].num[i] - 1 && i == b1); j ++)
printf("%d",i);
putchar(' ');
if(n % 2)
printf("7");
else
printf("1");
n = n / 2 - 1;
while(n --)
putchar('1');
putchar('\n');
}
}
return 0;
}
cal cal::AandB(cal a)
{
cal tmpCal;
tmpCal.length = length + a.length;
for(int i = 0 ; i < 10 ; i ++)
tmpCal.num[i] = num[i] + a.num[i];
tmpCal.num[0] += tmpCal.num[6];
tmpCal.num[6] = 0;
int j;
for( j = 1 ; j < 10 ; j ++)
if(tmpCal.num[j])
break;
int b1 = j;
if(tmpCal.num[0] && b1 > 6)
tmpCal.num[0] --,tmpCal.num[6] ++;
return tmpCal;
};
bool cal::sThan(cal a)
{
if(length < a.length)
return true;
else if(a.length > length)
return false;
else
{
int i;
for(i = 1 ; i < 10 ; i ++)
if(num[i])
break;
int b1 = i;
for(i = 1 ; i < 10 ; i ++)
if(a.num[i])
break;
int b2 = i;
if(b1 < b2)
return true;
else if(b1 > b2)
return false;
else
for(i = 0 ; i < 10 ; i ++)
if(a.num[i] != num[i])
return num[i] > a.num[i];
}
return false;
};
void cal::Equal(cal a)
{
for(int i = 0 ; i < 10 ; i ++)
num[i] = a.num[i];
length = a.length;
num[0] += num[6];
num[6] = 0;
int j;
for( j = 1 ; j < 10 ; j ++)
if(num[j])
break;
int b1 = j;
if(num[0] && b1 > 6)
num[0] --,num[6] ++;
}
然后是I题
其实I题很水,就是前两天写的点到线段距离的改版,只不过这是线段到线段间的最短距离
题目按顺时针或逆时针输入,数据量只有100,所以任然暴搜解决
代码如下:
#include<stdio.h>
#include<math.h>
double GetLineDistance(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4);
double disBetweenPointAndLine(double x0,double y0,double x1,double y1,double x2,double y2);
double X1[100],Y1[100],X2[100],Y2[100];
int main()
{
int t;
scanf("%d",&t);
while(t --)
{
int n,m,i,j;
double out = 100000000;
scanf("%d",&n);
for(i = 0 ; i < n ; i ++)
scanf("%lf %lf",&X1[i],&Y1[i]);
scanf("%d",&m);
for(i = 0 ; i < m ; i ++)
scanf("%lf %lf",&X2[i],&Y2[i]);
for(i = 0 ; i < n ; i ++)
for(j = 0 ; j < m ; j ++)
{
double tmpDou = GetLineDistance(X1[i],Y1[i],X1[(i + 1) % n],Y1[(i + 1) % n]
,X2[j],Y2[j],X2[(j + 1) % m],Y2[(j + 1) % m]);
if(out > tmpDou)
out = tmpDou;
};
printf("%.8lg\n",out / 2);
}
return 0;
}
//{(x1,y1),(x2,y2)}{(x3,y3),(x4,y4)}
//导入点到直线或线段的距离模板
double GetLineDistance(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4)
{
double tmpDouble = disBetweenPointAndLine(x1,y1,x3,y3,x4,y4);
if(tmpDouble > disBetweenPointAndLine(x2,y2,x3,y3,x4,y4))
tmpDouble = disBetweenPointAndLine(x2,y2,x3,y3,x4,y4);
if(tmpDouble > disBetweenPointAndLine(x3,y3,x1,y1,x2,y2))
tmpDouble = disBetweenPointAndLine(x3,y3,x1,y1,x2,y2);
if(tmpDouble > disBetweenPointAndLine(x4,y4,x1,y1,x2,y2))
tmpDouble = disBetweenPointAndLine(x4,y4,x1,y1,x2,y2);
return tmpDouble;
}
double disBetweenPointAndLine(double x0,double y0,double x1,double y1,double x2,double y2)
{
//化为ax+by+c=0的形式
double a = y1-y2;
double b = x2-x1;
double c = x1*y2-x2*y1;
double d = (a*x0+b*y0+c)/sqrt(a*a+b*b);
/*
如果是线段判断垂足
*/
double xp = (b*b*x0-a*b*y0-a*c)/(a*a+b*b);
double yp = (-a*b*x0+a*a*y0-b*c)/(a*a+b*b);
double xb = (x1>x2)?x1:x2;
double yb = (y1>y2)?y1:y2;
double xs = x1+x2-xb;
double ys = y1+y2-yb;
if(xp > xb || xp < xs || yp > yb || yp < ys)
{
d = sqrt((x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1));
if(d > sqrt((x0 - x2) * (x0 - x2) + (y0 - y2) * (y0 - y2)))
d = sqrt((x0 - x2) * (x0 - x2) + (y0 - y2) * (y0 - y2));
}
return fabs(d);
}
Last updated