2014编程之美挑战赛初赛 (程式之美初賽第一場)

website: http://hihocoder.com/contest/msbop2014r2a



P1 : 焦距

Time Limit: 2000ms
Case Time Limit: 1000ms
Memory Limit: 256MB

題目描述

一般來說,我們採用針孔相機模型,也就是認為它用到的是小孔成像原理。

在相機坐標系下,一般來說,我們用到的單位長度,不是「米」這樣的國際單位,而是相鄰圖元的長度。而焦距在相機坐標系中的大小,是在影像處理領域的一個非常重要的物理量。

假設我們已經根據相機參數,得到鏡頭的物理焦距大小(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為焦距在相機坐標系中的大小(focal length in pixels),保留小數點後2位有效數字,四捨五入取整。



資料範圍

對於小資料:focal length on earth和CCD width on earth單位都是毫米(mm)

對於大資料:長度單位還可能為米(m), 公寸(dm), 釐米(cm), 毫米(mm), 微米(um),納米(nm)



Sample Input
2
5.4mm 5.27mm 1600px
5400um 0.00527m 1600px
Sample Output
Case 1: 1639.47px
Case 2: 1639.47px
#include <cstdio>
#include <cstring>

using namespace std;

double adjust(char s[], double a) {
        if (strcmp(s, "m") == 0)
                return a * 1e9;
        else if (strcmp(s, "dm") == 0)
                return a * 1e8;
        else if (strcmp(s, "cm") == 0)
                return a * 1e7;
        else if (strcmp(s, "mm") == 0)
                return a * 1e6;
        else if (strcmp(s, "um") == 0)
                return a * 1e3;
        else if (strcmp(s, "nm") == 0)
                return a;
        return a;
}

int main() {
        int T;
        scanf("%d", &T);
        for (int casenum = 1; casenum <= T; ++casenum) {
                double a, b, c;
                char s[10], t[10];
                scanf("%lf%s%lf%s%lf%*s", &a, s, &b, t, &c);
                a = adjust(s, a);
                b = adjust(t, b);
                printf("Case %d: %.2lfpx\n", casenum, a / b * c);
        }
        return 0;
}











P2 : 樹

Time Limit: 4000ms
Case Time Limit: 2000ms
Memory Limit: 256MB

題目描述

有一個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 ≤ 105),表示樹的節點總數。

接下來N- 1行,每行1個數,a (1 ≤ a ≤ N),依次表示2..N節點的父親節點的編號。

接下來一個整數Q(1≤ Q ≤ 105),表示操作總數。

接下來Q行,每行4個整數,u, l, r, delta (1 ≤ u ≤ N, 1 ≤ l ≤ r ≤ N, -109≤ delta ≤ 109),代表一次操作。


輸出

對每組資料,先輸出一行「Case x: 」,x表示是第幾組資料,然後接這組資料答案的Hash值。


資料範圍

小資料:1 ≤ N, Q ≤ 1000

大資料:1 ≤ N, Q ≤ 105



樣例解釋


點1的子樹中有1,2,3三個節點。其中深度在2-3之間的是點2和點3。

點2的子樹中有2,3兩個節點。其中沒有深度為1的節點。

所以,執行完所有操作之後,只有2,3兩點的權值增加了1。即答案是0 1 1。再計算對應的Hash值即可。



Sample Input
1
3
1
2
2
1 2 3 1
2 1 1 1
Sample Output
Case 1: 12348
#include <cstdio>
#include <vector>
#include <queue>

using namespace std;

const long long MOD = 1000000007;
const long long MAGIC = 12347;

int calc(const int u, const vector<int> &depth, const vector<vector<int> > &child,
        vector<int> &height) {
        const int n = child[u].size();
        if (n == 0) {
                height[u] = depth[u];
                return height[u];
        }
        int h = 0;
        for (int i = 0; i < n; ++i)
                h = max(h, calc(child[u][i], depth, child, height));
        height[u] = h;
        return h;
}

void add(const int u, const int l, const int r, const int delta,
        const vector<int> &depth, const vector<int> &height, const vector<vector<int> > &child,
        vector<int> &weight) {
        if (depth[u] >= l) weight[u] += delta;
        if (depth[u] == r) return;
        int n = child[u].size();
        for (int i = 0; i < n; ++i) {
                int v = child[u][i];
                if (height[v] >= l && depth[v] <= r)
                        add(v, l, r, delta, depth, height, child, weight);
        }
}

int main() {
        int T;
        scanf("%d", &T);
        for (int casenum = 1; casenum <= T; ++casenum) {
                int n, qnum;
                scanf("%d", &n);
                vector<int> weight(n, 0);
                vector<vector<int> > child(n, vector<int>());
                for (int i = 1; i < n; ++i) {
                        int fa;
                        scanf("%d", &fa);
                        child[fa - 1].push_back(i);
                }
                vector<int> depth(n, 0), height(n, 0);
                depth[0] = 1;
                queue<int> q;
                q.push(0);
                while (!q.empty()) {
                        int u = q.front();
                        q.pop();
                        int m = child[u].size();
                        for (int i = 0; i < m; ++i) {
                                int v = child[u][i];
                                depth[v] = depth[u] + 1;
                                q.push(v);
                        }
                }
                calc(0, depth, child, height);

                scanf("%d", &qnum);
                while (qnum--) {
                        int u, l, r, delta;
                        scanf("%d%d%d%d", &u, &l, &r, &delta);
                        --u;
                        if (height[u] >= l && depth[u] <= r)
                                add(u, l, r, delta, depth, height, child, weight);
                }
                long long ans = 0;
                for (int i = 0; i < n; ++i)
                        ans = (ans * MAGIC + weight[i]) % MOD;
                printf("Case %d: %lld\n", casenum, ans);
        }
        return 0;
}














P3 : 活動中心

Time Limit: 12000ms
Case Time Limit: 6000ms
Memory Limit: 256MB

題目描述

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 ≤ 105

對於所有資料,座標值都是整數且絕對值都不超過106



樣例解釋


樣例1:活動中心的最優建造位置為(1.678787,0)



Sample Input
1
3
1 1
2 2
3 3
Sample Output
Case 1: 1.678787
#include <cstdio>
#include <cmath>
#include <cfloat>
#include <algorithm>

using namespace std;

const double eps = 1e-8;

struct Point{
        double x, y;
}p[100000];

double area(double x, int n) {
        double res = 0;
        for (int i = 0; i < n; ++i)
                res += sqrt((p[i].x - x) * (p[i].x - x) + p[i].y * p[i].y);
        return res;
}

int main() {
        int T;
        scanf("%d", &T);
        for (int casenum = 1; casenum <= T; ++casenum) {
                int n;
                scanf("%d", &n);
                double low = DBL_MAX, high = -DBL_MAX;
                for (int i = 0; i < n; ++i) {
                        scanf("%lf%lf", &p[i].x, &p[i].y);
                        low = min(low, p[i].x);
                        high = max(high, p[i].x);
                }
                while (low + eps < high) {
                        double mid = (low + high) / 2;
                        double tmp = mid + 1e-5;        // 1e-6 WA, better use 三分
                        double a = area(mid, n), b = area(tmp, n);
                        if (a < b)
                                high = mid;
                        else
                                low = mid;
                }
                printf("Case %d: %.6lf\n", casenum, high);
        }
        return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值