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

    全国信息学分区联赛模拟试题(七)

    【试题概览】

    试题名称 猴子
    提交文件 tower circle monkey hill
    输入文件 tower.in circle.in monkey.in hill.in
    输出文件 tower.out circle.out monkey.out hill.out
    时间限制 1s 1s 1s 1s
    空间限制 128MB 128MB 128MB 128MB

    题目来源 Topcoder Topcoder POIX COI2004

    题目描述

    给出 N 个木块,告诉你每块木块的高度,你要用这些木块搭出两座高度相同的塔,一座塔的高度为搭建它的木块的 高度和,并且一座塔至少要用一块木头。木块只能用一次,也可以不用。问在两座塔的高度相同的限制下,能够搭 的塔的最大高度是多少? 【输入文件】 第一行一个整数 N,表示木块个数; 第二行 N 个整数,表示 N 块木块的高度。 ## 输出文件
    仅一个数,表示能搭建的最高的塔的高度,若不不能搭建两座相同高度的塔,输出-1。

    样例输入

    3
    2 3 5

    样例输出

    5

    数据规模

    N<=50,每块木块的高度范围[1,500000],所有木块的高度总和<=500000。

    题解

    又是一个杂技DP,好像叫什么差值DP,dp[i][j]表示利用前i个木块,搭出两个差为j的塔,其中最高的塔的较矮的那个高度,那么分三种情况讨论,

    dp[i][j]=max(dp[i-1][j-h[i]],dp[i-1][h[i]-j]+h[i]-j,dp[i-1][j+h[i]]+h[i])
    

    然后乱搞就行

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #define LL long long
    #define INF (1<<30)
    using namespace std;
    
    int dp[61][500006],n;
    int h[100],sum;
    
    int main(){
    	freopen("tower.in","r",stdin);
    	freopen("tower.out","w",stdout);
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    		scanf("%d",&h[i]),sum+=h[i];
    	for(int i=0;i<=n;i++)for(int j=0;j<=sum;j++)dp[i][j]=-INF;
    	dp[0][0]=0;
    	for(int i=1;i<=n;i++){
    		for(int j=0;j<=sum;j++){
    			dp[i][j]=dp[i-1][j];
    			if(j>=h[i])
    				dp[i][j]=max(dp[i][j],dp[i-1][j-h[i]]);
    			if(j<=h[i])
    				dp[i][j]=max(dp[i][j],dp[i-1][h[i]-j]+h[i]-j);
    			dp[i][j]=max(dp[i][j],dp[i-1][j+h[i]]+h[i]);
    		}
    	}
    	printf("%d",dp[n][0]);
    }
    /*
    5
    1 4 2 3 65
    
    */
    

    题目描述

    给出 N 个圆,保证任意两个圆都是相离的,然后给出两个点(x1,y1)、(x2,y2),保证均不在某个圆上,要从(x1,y1)到 (x2,y2)画条曲线,问这条曲线最少要穿过多少次圆的边界?

    输入文件

    第一行一个整数 N,表示圆的个数; 第二行 N 个整数,表示 N 个圆的 X 坐标; 第三行 N 个整数,表示 N 个圆的 Y 坐标; 第四行 N 个整数,表示 N 个圆的半径 R; 第五行四个整数 x1,y1,x2,y2。

    输出文件

    仅一个数,表示最少要穿过多少次圆的边界。

    样例输入 1

    1

    0

    0

    2

    -5 1 5 1

    样例输出 1

    0

    样例输入 2

    7

    1 -3 2 5 -4 12 12
    1 -1 2 5 5 1 1
    8 1 2 1 1 1 2
    -5 1 12 1

    样例输出 2

    3

    数据规模

    1<=N<=50,坐标范围[-1000,1000],每个圆的半径 1<=R<=1000。 保证没有两个圆有公共点,起点和终点不会落在某个圆的边界上。

    题解

    对于每一个圆,如果两个点一个在圆内,一个在圆外,那么一定要穿过这个圆,ans++即可

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define LL long long
    #define INF (1<<30)
    using namespace std;
    
    
    struct Point{
    	int x,y;
    	Point(int xx=0,int yy=0)
    		{x=xx;y=yy;}
    }a,b;
    struct Circle{
    	Point o;
    	int r;
    	Circle(Point oo=Point(0,0),int rr=0)
    		{o=oo;r=rr;}
    }c[100];
    int dis(Point A,Point B){
    	return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);
    }
    int n,ans;
    int main(){
    	freopen("circle.in","r",stdin);
    	freopen("circle.out","w",stdout);
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    		scanf("%d",&c[i].o.x);
    	for(int i=1;i<=n;i++)
    		scanf("%d",&c[i].o.y);
    	for(int i=1;i<=n;i++)
    		scanf("%d",&c[i].r);
    	scanf("%d%d%d%d",&a.x,&a.y,&b.x,&b.y);
    	for(int i=1;i<=n;i++)
    		if(((LL)(dis(c[i].o,a)-c[i].r*c[i].r))*((dis(c[i].o,b)-c[i].r*c[i].r))<0ll)ans++;
    	printf("%d",ans);
    }
    
    
    /*
    7 
    1 -3 2 5 -4 12 12 
    1 -1 2 5 5 1 1 
    8 1 2 1 1 1 2 
    -5 1 12 1 
    
    */
    

    猴子

    题目描述

    有 N 只猴子,第一只尾巴挂在树上,剩下的 N-1 只,要么被其它的猴子抓住,要么抓住了其它的猴子,要么两者均 有。当然一只猴子最多抓两只另外的猴子,只有两只手嘛。现在给出这 N 只猴子抓与被抓的信息,并且在某个时刻 可能某只猴子会放掉左手或右手的猴子,导致某些猴子落在地上。求每只猴子落地的时间。

    输入文件

    第一行两个数 N、M,表示有 N 只猴子,并且总时间为 M-1。 接下来 N 行,描述了每只猴子的信息,每行两个数,分别表示这只猴子左手和右手抓的猴子的编号,如果是-1,表 示该猴子那只手没抓其它的猴子。再接下来 M 行,按时间顺序给出了一些猴子放手的信息,第 1+N+i 行表示第 i-1 时刻某只猴子的放手信息,信息以两个数给出,前者表示放手的猴子的编号,后者表示其放的哪只手,1 表示左手, 2 表示右手。

    输出文件

    共 N 行,第 i 行表示第 i 只猴子掉落的时刻,若第 i 只猴子到 M-1 时刻以后还没掉落,就输出-1。

    样例输入

    3 2

    -1 3

    3 -1

    1 2

    1 2

    3 1

    样例输出

    -1

    1

    1

    数据规模

    30%的数据,N<=1000,M<=1000; 100%的数据,1<=N<=200000,1<=M<=400000。

    题解

    考虑时光倒流,那么猴子就是从地上一个个地跳上去,用并查集做就好了,本题可能隐藏并查集的高级用法,还有待挖掘

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define LL long long
    #define INF (1<<30)
    using namespace std;
    
    int n,m;
    struct Edge{
    	int a,b;
    }e[1000000];
    int ch[200200][2];
    
    int fa[200200];
    void pre(){for(int i=1;i<=n;i++)fa[i]=i;}
    int findf(int x){return fa[x]==x?x:fa[x]=findf(fa[x]);}
    void mergef(int x,int y){fa[findf(x)]=findf(y);}
    
    int to[1000000],nt[1000000],fp[200200],cnt=1;
    void add(int x,int y){
    	to[cnt]=y;nt[cnt]=fp[x];
    	fp[x]=cnt++;
    }
    
    int ans[200200];
    void dfs(int k,int t){
    	ans[k]=t;
    	for(int i=fp[k];i;i=nt[i]){
    		int kk=to[i];
    		if(ans[kk]!=-1)continue;
    		dfs(kk,t);
    	}
    }
    int main(){
    	//freopen("monkey.in","r",stdin);
    	//freopen("monkey.out","w",stdout);
    	memset(ans,-1,sizeof(ans));
    	scanf("%d%d",&n,&m);pre();
    	for(int i=1;i<=n;i++)
    		scanf("%d%d",&ch[i][0],&ch[i][1]);
    	for(int i=1;i<=m;i++){
    		int p,c;
    		scanf("%d%d",&p,&c);c--;
    		if(ch[p][c]==-1)continue;
    		e[i].a=p;e[i].b=ch[p][c];	
    		ch[p][c]=-1;
    	}
    	for(int i=1;i<=n;i++){
    		if(ch[i][0]!=-1){
    			if(findf(i)==findf(ch[i][0]))continue;
    			mergef(i,ch[i][0]);
    			add(i,ch[i][0]);
    			add(ch[i][0],i);
    		}
    		if(ch[i][1]!=-1){
    			if(findf(i)==findf(ch[i][1]))continue;
    			mergef(i,ch[i][1]);
    			add(i,ch[i][1]);
    			add(ch[i][1],i);
    		}	
    	}
    	for(int i=m;i>=1;i--){
    		int a=e[i].a,b=e[i].b;
    		if(a==0&&b==0)continue;
    		int Fa=findf(a),Fb=findf(b);
    		int root=findf(1);
    		if(Fa==Fb)continue;
    		if(Fa==root)dfs(Fb,i-1);
    		else if(Fb==root)dfs(Fa,i-1);
    		mergef(a,b);
    		add(a,b);
    		add(b,a);
    	}
    	for(int i=1;i<=n;i++)	
    		printf("%d
    ",ans[i]);
    } 
    
    /*
    3 2 
    -1 3 
    3 -1 
    1 2 
    1 2 
    3 1
    
    
    10 15
    5 -1
    6 -1
    -1 10
    9 9
    9 10
    -1 7
    10 -1
    5 1
    4 3
    9 3
    6 2
    5 2
    8 1
    5 1
    10 1
    3 2
    4 1
    4 2
    8 2
    1 1
    9 1
    10 2
    7 1
    2 1
    9 2
    
    
    */
    

    题目描述

    给一座山,如图所示
    现在要在山上的某个部位装一盏灯,使得这座山的任何一个部位都能够被看到。给出最小的 y 坐标,如图的+号处 就是 y 坐标最小的安装灯的地方。

    输入文件

    第一行一个数 N,表示这座山有 N 个点构成,接下来 N 行从左到右给出了这座山的构造情况,每行两个数 Xi,Yi, 表示一个折点,保证 Xi>Xi-1(1<i<=N)。

    输出文件

    仅输出一行,为最小的 y 坐标,当你的答案与标准答案相差 0.01 时,则被认为是正确的。

    样例输入

    6

    0 0

    10 0

    11 1

    15 1

    16 0

    25 0

    样例输出

    3.00

    数据规模

    30%的数据,1<=N<=50;

    100%的数据,1<=N<=5000,0<=Xi,Yi<=100000,保证答案不超过 1000000。

    题解

    大神口中的半平面交,那么我们直接二分纵坐标,看看是否存在横坐标的取值集合,判断即可

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #define LL long long
    #define INF (1<<30)
    #define eps (1e-8)
    using namespace std;
    
    int n;double ans;
    struct Point{
    	double x,y;
    	Point(double xx=0,double yy=0)
    		{x=xx;y=yy;}
    }p[10000];
    struct Line{
    	Point a,b;
    	Line(Point aa,Point bb)
    		{a=aa;b=bb;}
    };
    bool check(double y){
    	double L=0,R=1000000;
    	for(int i=1;i<n;i++){
    		double k=(p[i].y-p[i+1].y)/(p[i].x-p[i+1].x);
    		if(abs(k)<eps){
    			if(y<p[i].y)return false;
    		}
    		else {
    			double x=(y-p[i].y)/k+p[i].x;
    			if(k>0)R=min(R,x);
    			else L=max(L,x);
    		}
    		if(L>R)return false;
    	}
    	return true;
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    		scanf("%lf%lf",&p[i].x,&p[i].y);
    	double L=0,R=1000000;
    	while(L+0.001<R){
    		ans=(L+R)/2;
    		if(check(ans))R=ans;
    		else L=ans;
    	}
    	printf("%.2lf",ans);
    }
    /*
    6 
    0 0 
    10 0 
    11 1 
    15 1 
    16 0 
    25 0
    
    6
    0 10
    3 7
    5 0
    6 1
    7 4
    10 5
    */
    
  • 相关阅读:
    Linux入门实践笔记(二)——Jar包的运行与关闭
    SpringCloud从入门到进阶(二)——注册中心Eureka的伪分布式部署
    Linux入门实践笔记(一)——安装JDK与运行jar包
    探究ConcurrentHashMap中键值对在Segment[]的下标如何确定
    探究HashMap线性不安全(三)——死循环的产生
    jmeter集成测试报告
    jmeter+ant+jenkins持续集成设置
    jmeter-环境配置与安装
    MySql 基本语法_数据表操作
    MySql 基本语法_数据库操作
  • 原文地址:https://www.cnblogs.com/Anoxiacxy/p/7189532.html
Copyright © 2011-2022 走看看