2014-04-19编程之美初赛题目及答案解析

第一题:

描述

一般来说,我们采用针孔相机模型,也就是认为它用到的是小孔成像原理。

在相机坐标系下,一般来说,我们用到的单位长度,不是“米”这样的国际单位,而是相邻像素的长度。而焦距在相机坐标系中的大小,是在图像处理领域的一个非常重要的物理量。

假设我们已经根据相机参数,得到镜头的物理焦距大小(focal length),和相机胶片的宽度(CCD width),以及照片的横向分辨率(image width),则具体计算公式为:

Focal length in pixels = (image width in pixels) * (focal length on earth) / (CCD width on earth)

比如说对于Canon PowerShot S100, 带入公式得

Focal length in pixels = 1600 pixels * 5.4mm / 5.27mm = 1639.49 pixels

现在,请您写一段通用的程序,来求解焦距在相机坐标系中的大小。

输入

多组测试数据。首先是一个正整数T,表示测试数据的组数。

每组测试数据占一行,分别为

镜头的物理焦距大小(focal length on earth)

相机胶片的宽度(CCD width on earth)

照片的横向分辨率大小(image width in pixels),单位为px。

之间用一个空格分隔。

输出

每组数据输出一行,格式为“ Case X: Ypx ”。 X为测试数据的编号,从1开始;Y为焦距在相机坐标系中的大小(focallength in pixels),保留小数点后2位有效数字,四舍五入取整。

数据范围

对于小数据:focal length on earth和CCD width on earth单位都是毫米(mm)

对于大数据:长度单位还可能为米(m), 分米(dm), 厘米(cm), 毫米(mm), 微米(um),纳米(nm)

解析:

代码:

//source here
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;

int main(){
 int icase;
 cin>>icase;
 double x,y,z;
 string a,b,c;
 for(int i= 1; i<= icase; ++i){
  cin>>x>>a>>y>>b>>z>>c;
  if(a=="m"){
   x*=1000;
  }else if(a=="dm"){
   x*=100;
  }else if(a=="cm"){
   x*=10;
  }else if(a=="um"){
   x/=1000;
  }else if(a=="nm"){
   x/=1000000;
  }
  if(b=="m"){
   y*=1000;
  }else if(b=="dm"){
   y*=100;
  }else if(b=="cm"){
   y*=10;
  }else if(b=="um"){
   y/=1000;
  }else if(b=="nm"){
   y/=1000000;
  }
  double tt= x*z/y;
  printf("Case %d: %.2lfpx\n",i, tt);
 }
}

第二题:

描述

有一个N个节点的树,其中点1是根。初始点权值都是0。

一个节点的深度定义为其父节点的深度+1,。特别的,根节点的深度定义为1。

现在需要支持一系列以下操作:给节点u的子树中,深度在l和r之间的节点的权值(这里的深度依然从整个树的根节点开始计算),都加上一个数delta。

问完成所有操作后,各节点的权值是多少。

为了减少巨大输出带来的开销,假设完成所有操作后,各节点的权值是answer[1..N],请你按照如下方式计算出一个Hash值(请选择合适的数据类型,注意避免溢出的情况)。最终只需要输出这个Hash值即可。

MOD =1000000007; // 10^9 + 7

MAGIC= 12347;

Hash =0;

For i= 1 to N do

   Hash = (Hash * MAGIC + answer[i]) mod MOD;

EndFor

输入

第一行一个整数T (1 ≤ T ≤ 5),表示数据组数。

接下来是T组输入数据,测试数据之间没有空行。

每组数据格式如下:

第一行一个整数N (1 ≤ N ≤ 10 5 ),表示树的节点总数。

接下来N – 1行,每行1个数,a (1 ≤ a ≤ N),依次表示2..N节点的父亲节点的编号。

接下来一个整数Q(1 ≤ Q ≤ 10 5 ),表示操作总数。

接下来Q行,每行4个整数,u, l, r, delta (1 ≤ u ≤ N, 1 ≤ l ≤ r ≤ N, -10 9  ≤ delta ≤ 10 9),代表一次操作。

输出

对每组数据,先输出一行“ Case x:  ”,x表示是第几组数据,然后接这组数据答案的Hash值。

数据范围 

小数据:1 ≤ N, Q ≤ 1000

大数据:1 ≤ N, Q ≤ 10 5

分析:

//source here

#include <iostream>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <queue>
using namespace std;

const int NODE_COUNT= 100001;
vector<int>	child[NODE_COUNT];
long long	val[NODE_COUNT];
long long	parent[NODE_COUNT];
int		level[NODE_COUNT];
int node;
long long MOD =1000000007; // 10^9 + 7

long long MAGIC= 12347;
void BuildLevel();
void Change(int u,int r,int l, int delta);
long long hash();
int main(){
 int icase;
 cin>>icase;
 int c;
 for(int i= 1; i<= icase; ++i){
  scanf("%d",&node);
  memset(val,0,NODE_COUNT*sizeof(int));
  for(int l= 0; l< node; ++l){//empty child
   child[l].clear();
  }
  level[0]= 1;
  for(int l= 1; l< node; ++l){
   scanf("%d",&c);
   --c;
   parent[l]=c;
   child[c].push_back(l);
  }
  BuildLevel();
  int r,l,delta,u;
  int x;
  scanf("%d",&x);
  while(x--){
   cin>>u>>l>>r>>delta;
   --u;
   Change(u,l,r,delta);
  }
  cout<<"Case "<<i<<": "<<::hash()<<endl;
 }
}

void Change(int u,int l,int r, int delta){
 queue<int> q;
 q.push(u);
 int now;
 while(!q.empty()){
  now= q.front();
  vector<int>& lhs= child[now];
  q.pop();
  if(level[now]>= l && level[now]<= r){//[l,r]
   val[now]+=delta;

  }else if(level[now]>r){
   continue;
  }
  for(int i= 0; i< lhs.size();++i){
   q.push(lhs[i]);
  }
 }
}

long long hash(){
 long long s= 0;
 for(int i= 0; i< node; ++i){
  s= (s*MAGIC+val[i])%MOD;
 }
 return s;
}

void BuildLevel(){
 queue<int> q;
 level[0]= 1;
 q.push(0);
 int now;
 while(!q.empty()){
  now= q.front();
  q.pop();
  vector<int>& lhs= child[now];
  for(int i= 0; i< lhs.size(); ++i){
   level[lhs[i]]= level[now]+1;
   q.push(lhs[i]);
  }
 }
}

第三题:

描述

A市是一个高度规划的城市,但是科技高端发达的地方,居民们也不能忘记运动和锻炼,因此城市规划局在设计A市的时候也要考虑为居民们建造一个活动中心,方便居住在A市的居民们能随时开展运动,锻炼强健的身心。

城市规划局希望活动中心的位置满足以下条件:

1. 到所有居住地的总距离最小。

2. 为了方便活动中心的资源补给和其他器材的维护,活动中心必须建设在A市的主干道上。

为了简化问题,我们将A市摆在二维平面上,城市的主干道看作直角坐标系平的X轴,城市中所有的居住地都可以看成二维平面上的一个点。

现在,A市的城市规划局希望知道活动中心建在哪儿最好。

输入

第一行包括一个数T,表示数据的组数。

接下来包含T组数据,每组数据的第一行包括一个整数N,表示A市共有N处居住地

接下来N行表示每处居住地的坐标。

输出

对于每组数据,输出一行“ Case X: Y ”,其中X表示每组数据的编号(从1开始),Y表示活动中心的最优建造位置。我们建议你的输出保留Y到小数点后6位或以上,任何与标准答案的绝对误差或者相对误差在10 -6 以内的结果都将被视为正确。

数据范围

小数据:1 ≤ T ≤ 1000, 1 ≤ N ≤ 10

大数据:1 ≤ T ≤ 10, 1 ≤ N ≤ 10 5

对于所有数据,坐标值都是整数且绝对值都不超过10 6

解析:

//source here
#include <iostream>
#include <vector>
#include <stdio.h>
#include <utility>
#include <algorithm>
#include <string>
#include <math.h>
using namespace std;
vector<pair<double,double> > point;
const double EPSI= 0.000000001;

bool operator < (const pair<double,double>& lhs, const pair<double,double>& rhs){
 return lhs.first< rhs.first;
}

bool Check(double x);

int main(){
 int icase;
 cin>>icase;
 pair<double,double> pt;
 int ic;
 double l,h,mid;
 for(int i= 1; i<= icase; ++i){
  cin>>ic;
  point.clear();
  while(ic--){
   cin>>pt.first>>pt.second;
   point.push_back(pt);
  }
  sort(point.begin(),point.end());
  l= point[0].first;
  h= point[point.size()-1].first;
  while(fabs(l-h)>= EPSI){
   mid= (l+h)/2;
   if(Check(mid)){//>=0
    h= mid;
   }else{
    l= mid;
   }
  }
  printf("Case %d: %.6lf\n",i,mid);
 }
}

bool Check(double x){
 double sum= 0;
 int len= point.size();
 double a,b;
 for(int i= 0; i< len; ++i){
  a= x-point[i].first;
  b= sqrt(a*a+(point[i].second*point[i].second));
  sum+=a/b;
 }
 return sum>= 0;
}

    原文作者:kunlong0909
    原文地址: https://blog.csdn.net/kunlong0909/article/details/24120343
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞