编程之美 2014 初赛第一场

先上代码。。。

题目解析和测试用例,稍后会给出微软官方的解析

1. 焦距(字符串处理):

/*
 * main.cpp
 *
 *  Created on: 2014-4-19
 *      Author: zy
 */

#include<iostream>
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<cstdlib>
#include<iomanip> //setprecision控制小数点的个数

using namespace std;

double change(string s,int length)
{
	char a[100]={0};
	double mul;
	//用switch处理比if语句,可以节省很多代码,,,
	switch(s[length-2]) {
		case 'd': mul = 1e8;s[length-2] = 0;break;
		case 'c': mul = 1e7;s[length-2] = 0;break;
		case 'm': mul = 1e6;s[length-2] = 0;break;
		case 'u': mul = 1e3;s[length-2] = 0;break;
		case 'n':case 'p': mul = 1; s[length-2] = 0;break;
		default : mul = 1e9;s[length-1] = 0;
	}
	s.copy(a,s.size(),0);   //不要这句话,下面的字符串到double型会报错,或者从string 到char *强制转化下
	double ret = atof(a);
	return ret*mul;
}

int main()
{
	int T;
	cin >> T;
	double result=0;
	int count = 1;
	string s1,s2,s3;
	while(T--) {
		//输入数据,做相应替换:5.4mm 5.27mm 1600px
		cin >> s1 >> s2 >> s3;
		double x,y,z;
		//获取字符串中的单位,并进行转换(nm,不用有除法)
		x = change(s1,s1.size());
		y = change(s2,s2.size());
		z = change(s3,s3.size());

		result = z*x/y;
		//输出结果
		cout<<"Case "<< count<<": ";
		cout << fixed << setprecision(2) << result<< "px" <<endl;
		count++;
	}
	result = 0;
}

2. 树(同学写的,菜鸟表示不太会,,,注释是我加的,大家先不要看注释,直接看代码,代码我还没理解透):

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<iostream>
#include<sstream>
#include<queue>
using namespace std;
#define ll long long
const ll mod=1000000007LL,MG=12347LL;
int T,cas=0,N,st[100005],e,h[100005];
vector<int> L[100005],R[100005],del[100005];
ll tr[100005],num[100005];
struct EG
{
    int v,nx;
}eg[100005];
void add(int u,int v)
{
    eg[e].v=v;eg[e].nx=st[u];st[u]=e++;
}
void update(int k,int v)
{
    v%=mod;
    for(;k<=N;k+=k&-k)
    {
        tr[k]+=v;
        if(tr[k]>=mod)tr[k]-=mod;
    }
}
ll read(int k)
{
    ll ret=0;
    for(;k;k-=k&-k)
    {
        ret+=tr[k];
        if(ret>=mod)ret-=mod;
    }
    return ret;
}
//根据每个节点的度数和一个公式,来计算最终输出的结果
ll cal()
{
    ll ans=0;
    for(int i=1;i<=N;i++)
    {
        ans=(ans*MG+num[i])%mod;
    }
    return ans;
}
//dfs--深度优先算法,u:节点,hh:深度
void dfs(int u,int hh)
{
    h[u]=hh;
    int sz=L[u].size();
    for(int i=0;i<sz;i++)
    {
        update(L[u][i],del[u][i]);
        update(R[u][i]+1,-del[u][i]);
        //printf("%d - %d %d %d\n",u,L[u][i],R[u][i],del[u][i]);
    }
    //printf("%d %d\n",u,h[u]);
    num[u]=read(h[u]);
    for(int i=st[u];~i;i=eg[i].nx)
    {
        int v=eg[i].v;
        dfs(v,hh+1);
    }
    for(int i=0;i<sz;i++)
    {
        update(L[u][i],-del[u][i]);
        update(R[u][i]+1,del[u][i]);
    }
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        //N个节点
        scanf("%d",&N);
        e=0;
        //节点的状态,-1表示没有被访问过
        memset(st,-1,sizeof(st));
        int fa;
        //输入节点的父节点信息,并存储
        for(int i=2;i<=N;i++)
        {
            scanf("%d",&fa);
            add(fa,i);
        }
        //初始化以下几个结构体,节点度数的左右范围/
        for(int i=1;i<=N;i++)
        {
            L[i].clear();
            R[i].clear();
            del[i].clear();
        }
        int Q,u,l,r,d;
        //输入操作的个数
        scanf("%d",&Q);
        while(Q--)
        {
            scanf("%d%d%d%d",&u,&l,&r,&d);
            //将用户输入的深度范围存储起来
            L[u].push_back(l);
            R[u].push_back(r);
            del[u].push_back(d);
        }
        memset(tr,0,sizeof(tr));

        //核心算法,dfs-深度优先搜索遍历
        dfs(1,1);
        printf("Case %d: %lld\n",++cas,cal());
    }
}
/*
10
12
1 1 2 2 2 2 3 3 3 10 11
*/

3 . 活动中心(类似于之前的一个集会的问题,用的三分法):

/*
 * main.cpp
 *
 *  Created on: 2014-4-19
 *      Author: zy
 */

#include<iostream>
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>   //pow函数所需要的头文件
#include<iomanip> //setprecision控制小数点的个数

using namespace std;
long long x[500000],y[500000];
const double eps = 1e-6;  //精度
int N;

double cal(double m)
{
	double ans = 0;
	for(int i =0; i< N; i++) {
		double len=sqrt((x[i]-m)*(x[i]-m)+y[i]*y[i]);
		ans = ans + len;
	}
	return ans;
}
int main()
{
	int T;
	cin >> T;
	double result;  //输出结果
	int count = 1;
	while(T--) {
		//输入数据,做相应替换
		cin >> N;
		for(int i=0; i<N; i++) {
			cin >> x[i] >> y[i];
		}

		//核心算法
		double left = -1000000;
		double right = 1000000;

//三分查找算法
		while(1) {
			double mid = (left+right)/2;
			double midMid = (mid+right)/2;
			double retMid = cal(mid);
			double retMidMid = cal(midMid);

			if(retMid < retMidMid) right = midMid;
			else left = mid;
			if(right - left < eps) {
				result = right;
				break;
			}
		}
		//输出结果,控制double型的小数点位数
		cout<<"Case "<< count<<": ";
		cout << fixed << setprecision(6) << result<<endl;
		count++;

	}
	result = 0;
}


你可能感兴趣的:(算法,编程之美)