首页 > 代码库 > CUGBACM_Summer_Tranning3

CUGBACM_Summer_Tranning3

A.ZOJ3726 Alice‘s Print Service

题解 here

这道题在HDU上要用I64d 在ZOJ上要用lld


C.ZOJ3728 Collision

几何题,分几种情况:和大圆相离、和大圆相交和小圆相离、和大圆相交小圆也相交。

还有一种情况需要考虑,它飞的方向远离圆则永远不相交。


借用土豪的神模板

#include<cstring>
#include<string>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<ctime>
#include<cstdlib>
#include<functional>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define MAXN 1010
#define eps 1e-8
#define INF 0x7FFFFFFF
#define long long ll;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

struct point {
    double x,y;
};

double xmult(point p1,point p2,point p0)
{
    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}

double Distance(point p1,point p2)
{
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}

double disptoline(point p,point l1,point l2)
{
    return fabs(xmult(p,l1,l2))/Distance(l1,l2);
}

point intersection(point u1,point u2,point v1,point v2)
{
    point ret=u1;
    double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))
             /((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));
    ret.x+=(u2.x-u1.x)*t;
    ret.y+=(u2.y-u1.y)*t;
    return ret;
}

//判直线和圆相交,包括相切
int intersect_line_circle(point c,double r,point l1,point l2)
{
    if(disptoline(c,l1,l2)-r>-eps) {
        return 0;
    } else {
        return 1;
    }
}

//判线段和圆相交,包括端点和相切
int intersect_seg_circle(point c,double r,point l1,point l2)
{
    double t1=Distance(c,l1)-r,t2=Distance(c,l2)-r;
    point t=c;
    if (t1<eps||t2<eps) {
        return t1>-eps||t2>-eps;
    }
    t.x+=l1.y-l2.y;
    t.y+=l2.x-l1.x;
    return xmult(l1,c,t)*xmult(l2,c,t)<eps&&disptoline(c,l1,l2)-r<eps;
}

//判圆和圆相交,包括相切
int intersect_circle_circle(point c1,double r1,point c2,double r2)
{
    return Distance(c1,c2)<r1+r2+eps&&Distance(c1,c2)>fabs(r1-r2)-eps;
}

//计算圆上到点p最近点,如p与圆心重合,返回p本身
point dot_to_circle(point c,double r,point p)
{
    point u,v;
    if (Distance(p,c)<eps) {
        return p;
    }
    u.x=c.x+r*fabs(c.x-p.x)/Distance(c,p);
    u.y=c.y+r*fabs(c.y-p.y)/Distance(c,p)*((c.x-p.x)*(c.y-p.y)<0?-1:1);
    v.x=c.x-r*fabs(c.x-p.x)/Distance(c,p);
    v.y=c.y-r*fabs(c.y-p.y)/Distance(c,p)*((c.x-p.x)*(c.y-p.y)<0?-1:1);
    return Distance(u,p)<Distance(v,p)?u:v;
}

//计算直线与圆的交点,保证直线与圆有交点
//计算线段与圆的交点可用这个函数后判点是否在线段上
void intersection_line_circle(point c,double r,point l1,point l2,point& p1,point& p2)
{
    point p=c;
    double t;
    p.x+=l1.y-l2.y;
    p.y+=l2.x-l1.x;
    p=intersection(p,c,l1,l2);
    t=sqrt(r*r-Distance(p,c)*Distance(p,c))/Distance(l1,l2);
    p1.x=p.x+(l2.x-l1.x)*t;
    p1.y=p.y+(l2.y-l1.y)*t;
    p2.x=p.x-(l2.x-l1.x)*t;
    p2.y=p.y-(l2.y-l1.y)*t;
}

//计算圆与圆的交点,保证圆与圆有交点,圆心不重合
void intersection_circle_circle(point c1,double r1,point c2,double r2,point& p1,point& p2)
{
    point u,v;
    double t;
    t=(1+(r1*r1-r2*r2)/Distance(c1,c2)/Distance(c1,c2))/2;
    u.x=c1.x+(c2.x-c1.x)*t;
    u.y=c1.y+(c2.y-c1.y)*t;
    v.x=u.x+c1.y-c2.y;
    v.y=u.y-c1.x+c2.x;
    intersection_line_circle(c1,r1,u,v,p1,p2);
}
int main ()
{
    double Rm,R,r,x,y,vx,vy;
    while(~scanf("%lf %lf %lf %lf %lf %lf %lf",&Rm,&R,&r,&x,&y,&vx,&vy)) {
        point O;
        O.x=0;
        O.y=0;
        point P;
        P.x=x;
        P.y=y;
        point Pd;
        Pd.x=x+vx/10;
        Pd.y=y+vy/10;
        point p1,p2,p3,p4;
        if(Distance(O,P)<Distance(O,Pd))  {
            printf("0\n");
            continue;
        }

        if(intersect_line_circle(O,R+r,P,Pd)==0) {
            printf("0\n");    //与大圆相离
            continue;
        } else if(intersect_line_circle(O,Rm+r,P,Pd)==0) { //与小圆相离
            intersection_line_circle(O,R+r,P,Pd,p1,p2);
            if(p1.x!=p2.x) {
                printf("%.3lf\n",fabs((p1.x-p2.x)/vx));
            } else {
                printf("%.3lf\n",fabs((p1.y-p2.y)/vy));
            }
        } else {
            intersection_line_circle(O,R +r,P,Pd,p1,p2);
            intersection_line_circle(O,Rm+r,P,Pd,p3,p4);
            if(p1.x!=p2.x) {
                printf("%.3lf\n",2*fabs((max(p1.x,p2.x)-max(p3.x,p4.x))/vx));
            } else {
                printf("%.3lf\n",2*fabs((max(p1.y,p2.y)-max(p3.y,p4.y))/vy));
            }
        }
    }
}
/*
5 20 1 0 100 0 -1
5 20 1 30 15 -1 0
5 20 1 0 21  1  0
*/


F.ZOJ3731 Winter‘s Coming

感觉就是个简单的搜索,但是hdu、uva上都没有人过,目前uva上唯一的那一发submission是我华丽的WA,杭电上十几发submission一半是我交的。。。。zoj上有两个人过,我没过,而且还是坏习惯一直dfs在写迷宫,没T,WA成了狗。我的想法是用lw数组来存放每行最右端的W,用rl数组存放每行最左端的L,初始lw赋比0小,rl赋比m大,从第一行lw和rl之间开始枚举dfs,每一行把max(lw,0)当左边界,min(rl,m)当右边界,感觉还是挺简单的题。。。但是还是没AC


G.ZOJ3732 Graph Reconstruction

我之前刚好做过一个一样的题,点击这里,还是Havel-Hakimi定理,这题唯一的区别就是如果有多种可能就输出两组结果。我YY了一下,每次第二大的度数开始减一,减到最后一个数时将这个度和它的下一个度比较(如果存在的话),如果它们度一样,说明存在多组解,然后再用Havel-Hakimi定理扫一遍,第一回排序对度一样的情况按id从大到小排序,第二回对度一样的情况按id从小到大排序,这样就能产生两组解了,网上还有交换的方法, 不过交换起来相应的边都要改变,时间上都要进行两遍Havel-Hakimi扫描,我觉得我的方法更好想一些,不过缺点是我的方法只能找到两种解,如果题目需要输出三种解还是要用交换的方法。不过。。。可能我写的太挫,至今WA成狗


H.ZOJ3733 Skycity



J.ZOJ3735 Josephina and RPG

dp[i][j]: 和前i个队伍交战后所选队伍是j的最高胜率

状态转移方程:
dp[i][j] = max(dp[i][j],dp[i-1][j]*P[j][no[i]]); //代表不换
dp[i][no[i]] = max(dp[i][no[i]],dp[i-1][j]*P[j][no[i]]);//代表换战队

#include<cstring>
#include<string>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<ctime>
#include<cstdlib>
#include<functional>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define MAXN 1010
#define eps 1e-11
#define INF 0x7FFFFFFF
#define long long ll;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

double a[150][150];
double dp[10010][150];
int r[10010];
int main(){
    int n,m,i,j;
    while(scanf("%d",&n)!=EOF){
        n = n*(n-1)*(n-2)/6;
        for(i=0;i<n;i++){
            for(j=0;j<n;j++){
                scanf("%lf",&a[i][j]);
            }
        }
        scanf("%d",&m);
        for(i=0;i<n;i++){
            dp[0][i] = 1;
            for(j=1;j<=m;j++)
                dp[j][i] = 0;
        }
        for(i=1;i<=m;i++){
            scanf("%d",&r[i]);
        }
        for(i=1;i<=m;i++){
            for(j=0;j<n;j++){
                dp[i][j]=max(dp[i][j],dp[i-1][j]*a[j][r[i]]);
                dp[i][r[i]]=max(dp[i][r[i]],dp[i-1][j]*a[j][r[i]]);
            }
        }
        double ans = 0;
        for(i=0;i<n;i++){
            if(dp[m][i]>ans)    ans = dp[m][i];
        }
        printf("%.6lf\n",ans);
    }
    return 0;
}