zoukankan      html  css  js  c++  java
  • [noip模拟赛2017.7.4]

    题目名称 穿越七色虹 四叶草魔杖 圣主的考验
    程序文件 rainbow clover domine
    输入文件 rainbow.in clover.in domine.in
    输出文件 rainbow.out clover.out domine.out
    每个测试点时限 1 秒 1 秒 2 秒
    内存限制 128 MB 128 MB 256 MB
    代码长度限制 4096 B
    测试点数目 10 10 10
    每个测试点分值 10 10 10
    是否有部分分

    评测环境: Intel(R) Core(TM) i3-370M CPU @2.40GHz 2.39GHz, 2.00GB RAM Cena 0.8.2 @ Windows 8 Enterprise x64 C++选手可以使用 %lld 或%I64d 输入输出 64 位整数。 最终评测时,所有编译命令均不打开任何优化开关。

    穿越七色虹(rainbow.pas/c/cpp)

    题目背景

    在 Nescafe27 和 28 中,讲述了一支探险队前往 Nescafe 之塔探险的故事…… 当两位探险队员以最快的时间把礼物放到每个木箱里之后,精灵们变身为一缕缕金带似
    的光,簇簇光芒使探险队员们睁不开眼睛。待一切平静下来之后,探险队员来到了一座宫殿 中,玉制的石椅上坐着两个人…… “你们就是……Nescafe 之塔护法中的两位?” “是的,我们就是神刀护法 xlk 和飞箭护法 riatre……你们来这里做什么?” “我们是前来拜访圣主和四位护法的……” “如果你们想见圣主和其它两位护法,你们必须穿过前方的七色彩虹。请随我来吧……”

    题目描述

    探险队员们跟随两位护法来到了七色虹前。七色虹,就是平面直角坐标系中赤橙黄绿青 蓝紫七个半圆,第 i 座(1<=i<=7)半圆形彩虹的圆心是(xi,0),半径是 ri,半圆上所有点的纵坐 标均为非负数。探险队员可以看做一条竖直的、长度等于身高的线段,线段的底端纵坐标为 0,最高的一位探险队员的身高为 h。 现在探险队员们要从(0,0)穿越七色虹到达(x0,0),穿越七色虹的过程中,探险队员的整 个身体必须始终在至少一个半圆形彩虹的内部。由于彩虹的半径 ri 可能太小了,不足以满 足这个条件,因此两位护法决定帮助他们把所有彩虹的半径都增大一个非负实数 r。探险队 员们想知道,r 最小是多少呢?

    输入格式

    第一行两个实数 h、x0,表示身高和目的地横坐标。 接下来七行每行两个实数 xi、ri,表示七座半圆形彩虹的圆心和半径。

    输出格式

    输出最小的 r,四舍五入保留 2 位小数。

    样例输入

    4.0 36.0

    0.0 4.0

    6.0 4.0

    12.0 4.0

    18.0 4.0

    24.0 4.0

    30.0 4.0

    36.0 4.0

    样例输出

    1.00

    数据范围与约定

    对于 100% 的数据,满足 0<=xi,x0<=10000,0<h<100

    题解

    我们可以二分答案R,
    对于每个圆,利用H求出每个圆覆盖的有效范围,并将此问题转化为区间覆盖问题,每次检查这些区间是否能完全覆盖[0,x0],以下附上AC代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #define INF (1<<30)
    using namespace std;
    
    double h,x[10],r[10],R;
    struct line{
    	double l,r;
    	line(double ll=INF,double rr=0){l=ll;r=rr;}
    }T[10];
    bool cmp(line a,line b){
    	return a.l<b.l;
    }
    bool check(){
    	for(int i=1;i<=7;i++){
    		if(h>r[i]+R)T[i]=line(-1,-1);
    		else{
    			double dx=sqrt((r[i]+R)*(r[i]+R)-h*h);
    			T[i]=line(x[i]-dx,x[i]+dx);
    		}
    	}
    	sort(T+1,T+8,cmp);
    	double s=0,t=0;
    	for(int i=1;i<=7;i++){
    		if(T[i].l>t)return false;
    		t=max(T[i].r,t);
    		if(t>=x[0])return true;
    	}
    	return false;
    }
    int main(){
    	freopen("rainbow.in","r",stdin);
    	freopen("rainbow.out","w",stdout);
    	scanf("%lf%lf",&h,&x[0]);
    	for(int i=1;i<=7;i++)
    		scanf("%lf%lf",&x[i],&r[i]);
    	double s=0,t=100000;
    	while(s+0.00001<t){
    		R=(s+t)/2;
    		if(check())t=R;
    		else s=R;
    	}
    	printf("%.2lf",R);
    }
    
    /*
    4.0 36.0 
    0.0 4.0 
    6.0 4.0 
    12.0 4.0 
    18.0 4.0
    24.0 4.0 
    30.0 4.0 
    36.0 4.0 
    */
    

    四叶草魔杖(clover.pas/c/cpp)

    题目背景

    陶醉在彩虹光芒笼罩的美景之中,探险队员们不知不觉已经穿过了七色虹,到达了目的 地,面前出现了一座城堡和小溪田园,城堡前的木牌上写着“Poetic Island”。 “这一定就是另外两位护法的所在地了……我们快进去吧!” 探险队员们快步进入了城堡,城堡大厅的羊毛沙发上坐着两个人。 “你们是 Nescafe 的护法吧?” “是的哦~ 我们就是圣剑护法 rainbow 和魔杖护法 freda~ 你们来这里做什么呢~” “我们是来拜访圣主和四位护法的……” “可是圣主 applepi 已经前往超自然之界的学校(Preternatural Kingdom University,简 称 PKU)修炼魔法了,要想见到他,必须开启 Nescafe 之塔与超自然之界的通道。但是圣主 规定,开启通道的方法不能告诉任何外人。我只能提示你们,开启通道的钥匙就与四位护法 有关 T_T” 探险队员环视四周,突然,其中一人的目光停留在了魔杖之上。“hoho~ 魔杖!传说中 开启异时空通道的钥匙不就叫四叶草魔杖吗?四叶草有力量、信心、希望和幸运四片叶子, 护法恰好有神刀、飞箭、圣剑、魔杖四位!aha~我找到答案了!” “好吧,那我们就满足你们的愿望~”

    题目描述

    魔杖护法 Freda 融合了四件武器,于是魔杖顶端缓缓地生出了一棵四叶草,四片叶子幻 发着淡淡的七色光。圣剑护法 rainbow 取出了一个圆盘,圆盘上镶嵌着 N 颗宝石,编号为 0~N-1。第 i 颗宝石的能量是 Ai。如果 Ai>0,表示这颗宝石能量过高,需要把 Ai 的能量传 给其它宝石;如果 Ai<0,表示这颗宝石的能量过低,需要从其它宝石处获取-Ai 的能量。保 证∑Ai =0。只有当所有宝石的能量均相同时,把四叶草魔杖插入圆盘中央,才能开启超自 然之界的通道。 不过,只有 M 对宝石之间可以互相传递能量,其中第 i 对宝石之间无论传递多少能量, 都要花费 Ti 的代价。探险队员们想知道,最少需要花费多少代价才能使所有宝石的能量都 相同?

    输入格式

    第一行两个整数 N、M。 第二行 N 个整数 Ai。 接下来 M 行每行三个整数 pi,qi,Ti,表示在编号为 pi 和 qi 的宝石之间传递能量需要花 费 Ti 的代价。数据保证每对 pi、qi 最多出现一次。

    输出格式

    输出一个整数表示答案。无解输出 Impossible。

    样例输入

    3 3

    50 -20 -30

    0 1 10

    1 2 20

    0 2 100

    样例输出

    30

    数据范围与约定

    对于 50% 的数据,2<=N<=8。

    对于 100% 的数据,2<=N<=16,0<=M<=N*(N-1)/2,0<=pi,qi<N,-1000<=Ai<=1000, 0<=Ti<=1000,∑Ai=0。

    题解

    这个题比较复杂,先floyd求传递闭包,然后dfs求连通块,在每个连通块中寻找A值和为0的集合,对于每个集合,求取其MST(最小生成树),当作一个背包,最后动态规划,合并那些背包,求得最终答案,下面是AC代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #define INF (1<<29)
    #define LL long long
    using namespace std;
    int N,M,A[20];
    int mp[20][20];
    bool Zp[20],vis[20];
    int Cm[20][20],cnt;
    int trs(int x){return (1<<x);}
    int rtrs(int x){int rtn=1;while(trs(rtn)!=x)rtn++;return rtn;}
    void read(){
    	scanf("%d%d",&N,&M);
    	for(int i=1;i<=N;i++)
    		scanf("%d",&A[i]);
    	for(int i=1;i<=N;i++)
    		for(int j=1;j<=N;j++)
    			mp[i][j]=INF;
    	for(int i=1;i<=M;i++){
    		int x,y,z;
    		scanf("%d%d%d",&x,&y,&z);
    		x++;y++;
    		mp[x][y]=z;
    		mp[y][x]=z;
    	}
    }
    void Floyd(){
    	for(int k=1;k<=N;k++)
    		for(int i=1;i<=N;i++)
    			for(int j=1;j<=N;j++)
    				if(i!=j&&mp[i][j]>mp[i][k]+mp[k][j])
    					mp[i][j]=mp[i][k]+mp[k][j];
    }
    void checkzp(){
    	for(int i=1;i<=N;i++)
    		if(!A[i])Zp[i]=true;
    }
    void dfs(int k){
    	vis[k]=true;
    	Cm[cnt][++Cm[cnt][0]]=k;
    	for(int i=1;i<=N;i++)
    		if(!vis[i]&&!Zp[i])
    			dfs(i);
    }
    void getset(){
    	for(int i=1;i<=N;i++)
    		if(!vis[i]&&!Zp[i]){
    			cnt++;
    			dfs(i);
    		}
    }
    bool checksum(){
    	for(int i=1;i<=cnt;i++){
    		int sum=0;
    		for(int j=1;j<=Cm[cnt][0];j++)
    			sum+=A[Cm[cnt][j]];
    		if(sum!=0)return false;
    	}
    	return true;
    }
    int bag[65536],tot,val[262144],F[262144];
    
    int Fa[20];
    void Pre(){for(int i=1;i<=N;i++)Fa[i]=i;}
    int Find(int x){return Fa[x]==x?x:Fa[x]=Find(Fa[x]);}
    void Merge(int x,int y){Fa[Find(x)]=Find(y);}
    
    struct edge{
    	int a,b,t;
    	edge(int aa=0,int bb=0,int tt=0)
    		{a=aa;b=bb;t=tt;}
    }E[65536];int Et;
    bool cmp(edge x,edge y){return x.t<y.t;}
    void add(int x,int y,int z){E[++Et]=edge(x,y,z);}
    int MST(int St){
    	Et=0;memset(E,0,sizeof(E));
    	for(int i=1;i<N;i++)if(trs(i)&St)
    		for(int j=i+1;j<=N;j++)if(trs(j)&St)
    			if(mp[i][j]!=INF)
    				add(i,j,mp[i][j]);
    	sort(E+1,E+1+Et,cmp);
    	Pre();
    	int rtn=0;
    	for(int i=1;i<=Et;i++){
    		int x=E[i].a,y=E[i].b;
    		if(Find(x)!=Find(y)){
    			Merge(x,y);
    			rtn+=E[i].t;
    		}
    	}
    	return rtn;
    }
    void search(int c,int k,int t,int sum,int St){
    	if(k>t+1)return;
    	if(St&&!sum){
    		bag[++tot]=St;
    		val[St]=MST(St);
    	}
    	int p=Cm[c][k];
    	search(c,k+1,t,sum+A[p],St|trs(p));
    	search(c,k+1,t,sum,St);
    }
    void getbag(){
    	for(int i=1;i<=cnt;i++)
    		search(i,1,Cm[i][0],0,0);
    }
    void DP(){
    	int Suc=0;
    	for(int i=1;i<=N;i++)if(!Zp[i])Suc|=(1<<i);
    	for(int i=2;i<=Suc;i+=2)F[i]=INF;
    	for(int i=1;i<=tot;i++){
    		int s1=bag[i];
    		F[s1]=val[s1];
    		for(int j=1;j<=tot;j++){
    			int s2=bag[j];
    			F[s1|s2]=min(F[s1|s2],F[s2]+val[s1]);
    		}
    	}
    	printf("%d
    ",F[Suc]);
    }
    int main(){
    	freopen("clover.in","r",stdin);
    	freopen("clover.out","w",stdout);
    	read();
    	Floyd();
    	checkzp();
    	getset();
    	if(!checksum()){
    		printf("Impossible");
    		return 0;
    	}
    	getbag();
    	DP();
    } 
    
    /*
    3 3 
    50 -20 -30
    0 1 10
    1 2 20 
    0 2 100 
    
    */
    
    

    圣主的考验(domine.pas/c/cpp)

    题目背景

    随着四叶草魔杖的插入,Nescafe 之塔的塔尖附近出现了光漩涡。随着一束光芒投下, 探险队员们面前出现了圣主的身影。 “参见圣主!” “大家好,我叫杜宇飞。我就是 Nescafe 的圣主 applepi。” “圣主,我们是专程前来拜访您的!”探险队员们万分激动。 “再有七天就是 Nescafe 镇塔之宝一年一度的封印之期了,你们可以留下来观看封印。 不过在这之前,我还是想考考你们……”

    题目描述

    若对于二叉树 T 的每个节点 v,其左子树的高度 L 和右子树的高度 R 均满足|L – R|≤1, 则这个树 T 有可能来自超自然之界。规定若某节点子树为空,则该子树的高度是 0。你的任 务是求有 N 个节点的可能来自超自然之界的树的数目。

    输入格式

    每个测试点包含若干个测试数据。 每个测试数据占一行,包含一个整数 N。 输入文件以 0 结尾。

    输出格式

    对于每个测试数据,在单独的一行内输出结果。由于结果可能会很大,你只需要输出答 案在十进制表示下的后九位。若答案不足九位,只需输出原答案。

    样例输入

    2

    3

    5

    30

    0

    样例输出

    2

    1

    6

    11307920

    数据范围与约定

    对于 30% 的测试点,N≤100。 对于 70% 的测试点,N≤1000。 对于 100% 的测试点,1≤N≤3000。

    题解

    先用DP,求出高度为H的树拥有节点数的范围[Min[H],Max[H]],
    顺便求出节点数为n的树高度的范围[L[n],R[n]];
    用 f[i][j]记录节点数为i,高度为j的树的形态有多少种,
    动态规划:

    f[i][j]=f[k][j-1]*f[i-k-1][j-1]+f[k][j-2]*f[i-k-1][j-1]+f[k][j-1]*f[i-k-1][j-2]
    

    下面是AC代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #define INF (1<<30)
    #define mod 1000000000
    #define LL long long
    using namespace std;
    int Min[100],Max[100];
    int f[3005][100];
    int g[3005][100];
    int ans[3000];
    int main(){
    	freopen("domine.in","r",stdin);
    	freopen("domine.out","w",stdout);
    	g[0][0]=true;f[0][0]=1;
    	Min[1]=1;Min[2]=2;Max[1]=1;Max[2]=3;
    	for(int i=3;i<=20;i++)
    		Min[i]=Min[i-1]+Min[i-2]+1,
    		Max[i]=Max[i-1]*2+1;	
    	for(int n=1;n<=3000;n++){
    		int h=1;while(Max[h]<n)h++;
    		while(Min[h]<=n){
    			int i=Min[h-2];
    			while(true){
    				int l=i,r=n-1-l;
    				if(r<Min[h-2])break;
    				f[n][h]=((((f[n][h]+(long long)f[l][h-1]*f[r][h-1]%mod)%mod+(long long)f[l][h-2]*f[r][h-1]%mod)%mod+(long long)f[l][h-1]*f[r][h-2]%mod)%mod)%mod;
    				i++;
    			}
    			ans[n]=(ans[n]+f[n][h])%mod;h++;
    		}
    	}	
    	while(true){
    		int n;scanf("%d",&n);
    		if(n==0)break;
    		printf(n>35?"%0.9d
    ":"%d
    ",ans[n]);
    	}
    }
    
    
  • 相关阅读:
    HDU 2054 A == B ?(找小数点)
    javaWeb_使用标签库简化jsp
    EC2的维护更新-总结篇及有效经验分享
    SSLStrip 终极版 —— location 瞒天过海
    华为部分真机调试无法显示log问题解决
    LeetCode
    Tcl脚本调用高层API实现仪表使用和主机创建配置的自己主动化測试用例
    web工程调用hadoop集群1.2
    3DShader之移位贴图(Displacement Mapping)
    Java 学习第一天
  • 原文地址:https://www.cnblogs.com/Anoxiacxy/p/7135987.html
Copyright © 2011-2022 走看看