zoukankan      html  css  js  c++  java
  • Codeforces 306D

    Codeforces 题目传送门 & 洛谷题目传送门

    中考终于结束了……简单写道题恢复下状态罢。

    首先这一类题目肯定没法用一般的方法解决,因此考虑用一些奇淫的乱搞做法解决这道题,不难发现,如果我们固定住了前 (n-1) 条边,那么第 (n) 条边的长度与前 (n-1) 条边的长度冲突的概率是小之又小了——这个用爪子想想即可明白。

    因此考虑一个乱搞做法,我们每次随机前 (n-1) 条边的长度 (l_1,l_2,cdots,l_{n-1}),然后从原点开始绕一圈每次旋转 (dfrac{2pi}{n}) 补全这个 (n) 边形,如果最后一条边的长度与前 (n-1) 条边长度均不同且在 ((0,1000]) 之内则直接输出。

    这样一来倒是避免边长度相同的问题了,但同时还会带来另一个问题,就是如果有可能我们随机出来的图形不是凸图形,比如说下图:

    解决方法倒也容易,把每条边随机的范围变小一点即可,我是将第 (i) 条边的长度设为 (600+0.1i) 然后 random_shuffle,这样就不太可能出现这样的情况了。

    思路出来了,剩下就是实现的问题了,旋转 (dfrac{2pi}{n}) 我拿复数乘法实现的,最后第 (n) 个点的位置需解个直线方程。

    随机次数最多大概是 (2)(别问我怎么知道的 qwq),时间复杂度 (mathcal O( ext{能过)})

    const int MAXN=100;
    const double Pi=acos(-1);
    const double EPS=1e-6;
    int n;
    double len[MAXN+5];
    struct point{
    	double x,y;
    	point(double _x=0,double _y=0):x(_x),y(_y){}
    	point operator +(const point &rhs) const{return point(x+rhs.x,y+rhs.y);}
    	point operator -(const point &rhs) const{return point(x-rhs.x,y-rhs.y);}
    	point operator *(const double &rhs) const{return point(x*rhs,y*rhs);}
    	point operator /(const double &rhs) const{return point(x/rhs,y/rhs);}
    	double operator ~() const{return sqrt(x*x+y*y);}
    } p[MAXN+5];
    int main(){
    	srand(time(0));scanf("%d",&n);
    	if(n<=4) return puts("No solution")&0;
    	double ang=2*Pi/n;
    	while(1){
    		for(int i=1;i<n;i++) len[i]=600+i*0.1;
    		random_shuffle(len+1,len+n);
    		p[1]=point(0,0);p[2]=point(len[1],0);
    		for(int i=3;i<=n;i++){
    			point dif=p[i-1]-p[i-2];
    			point coe=point(cos(ang),sin(ang));
    			point nw=point(dif.x*coe.x-dif.y*coe.y,dif.x*coe.y+dif.y*coe.x);
    			nw=nw*(len[i-1]/len[i-2]);
    			if(i^n) p[i]=p[i-1]+nw;
    			else{
    				double k1=nw.y/nw.x;
    				double b=p[i-1].y-k1*p[i-1].x;
    				double k2=tan(Pi/n*(n-2));
    				p[i].x=b/(k2-k1);p[i].y=k2*p[i].x;
    			}
    		} bool flg=(~(p[1]-p[n])<1000+EPS);
    		for(int i=1;i<n;i++) flg&=(fabs((~(p[1]-p[n]))-len[i])>EPS);
    		if(flg) break;
    	}
    	for(int i=1;i<=n;i++) printf("%.10lf %.10lf
    ",p[i].x,p[i].y);
    	return 0;
    }
    
  • 相关阅读:
    [置顶] 图书推荐:SQL Server 2012 T-SQL基础 Itzik Ben-Gan
    UVA1366-----Martian Mining------DP
    动态规划——最长公共子序列(LCS)
    需求分析挑战之旅(疯狂的订餐系统)(3)——背景-需要-需求规格
    JavaScript学习笔记(四十四) 装饰器
    C中的volatile用法
    Java注解Annotation学习
    非常好!讲逻辑回归的,讲得很透彻
    RPC的学习 & gprotobuf 和 thrift的比较
    僵尸进程学习 & 进程状态列表 & Linux信号学习
  • 原文地址:https://www.cnblogs.com/ET2006/p/Codeforces-306D.html
Copyright © 2011-2022 走看看