Codeforces Beta Round #2

codeforces 2A.Winner

codeforces 2B.The least round way

codeforces 2C.Commentator problem

这期题目想对感觉较难 A敲了十多分钟 B是想了很久才开始写的中间TLE无数次 C完全懵逼 不过最后发现用爬山算法?/模拟退火可以求解 拖了好几天今天终于把C好好的敲了一下 现在送上题解

A. Winner
time limit per test
1 second
memory limit per test
64 megabytes
input
standard input
output
standard output

The winner of the card game popular in Berland "Berlogging" is determined according to the following rules. If at the end of the game there is only one player with the maximum number of points, he is the winner. The situation becomes more difficult if the number of such players is more than one. During each round a player gains or loses a particular number of points. In the course of the game the number of points is registered in the line "name score", where name is a player's name, and score is the number of points gained in this round, which is an integer number. If score is negative, this means that the player has lost in the round. So, if two or more players have the maximum number of points (say, it equals to m) at the end of the game, than wins the one of them who scored at least m points first. Initially each player has 0 points. It's guaranteed that at the end of the game at least one player has a positive number of points.

Input

The first line contains an integer number n (1  ≤  n  ≤  1000), n is the number of rounds played. Then follow n lines, containing the information about the rounds in "name score" format in chronological order, where name is a string of lower-case Latin letters with the length from 1 to 32, and score is an integer number between -1000 and 1000, inclusive.

Output

Print the name of the winner.

Examples
input
3
mike 3
andrew 5
mike 2
output
andrew
input
3
andrew 3
andrew 2
mike 5
output
andrew

题目链接:http://codeforces.com/contest/2/problem/A

题解:输入选手姓名和分数 求最后得分最高的人 然后注意是分数最高可能很多人取第一个达到这个分数的人 然后分数可能负数 

思路比较清晰 map简单应用 第一次循环求出所有人的最后得分 然后最后得分中取出得分最高的人 最后重新判定一下谁先得到这个分数

AC代码:

#include <bits/stdc++.h>
using namespace std;
map<string, int> mp, m;
vector<string> vec;
vector<int> ve;
int ma = -0xffffff;
string winer;

int main() {
    string str;
    int score;
    int n;
    cin >> n;
    getchar();
    for(int i = 0; i <n; ++i) {
        cin >> str >> score;
        mp[str] += score;
        vec.push_back(str);
        ve.push_back(score);
    }

    map<string, int>::iterator it;
    for(it = mp.begin(); it != mp.end(); ++it) {
        ma = max(it->second, ma);
    }

    for(int i = 0; i < n; ++i) {
        m[vec[i]] += ve[i];
        if(m[vec[i]] >= ma && mp[vec[i]] == ma) {
            cout << vec[i] << endl;
            break;
        }
    }

    return 0;
}

B. The least round way
time limit per test
5 seconds
memory limit per test
64 megabytes
input
standard input
output
standard output

There is a square matrix n × n, consisting of non-negative integer numbers. You should find such a way on it that

  • starts in the upper left cell of the matrix;
  • each following cell is to the right or down from the current cell;
  • the way ends in the bottom right cell.

Moreover, if we multiply together all the numbers along the way, the result should be the least "round". In other words, it should end in the least possible number of zeros.

Input

The first line contains an integer number n (2 ≤ n ≤ 1000), n is the size of the matrix. Then follow n lines containing the matrix elements (non-negative integer numbers not exceeding 109).

Output

In the first line print the least number of trailing zeros. In the second line print the correspondent way itself.

Examples
input
3
1 2 3
4 5 6
7 8 9
output
0
DDRR

题目链接:http://codeforces.com/contest/2/problem/B

题解:从左上角到右下角经过的数字的乘积最后至少有几个0

dp 一个记录经过当前点最少的约数2的数目 一个记录经过当前点最少的约数5的数目 然后取抵达最后一个点2和5的数目最少的那个 TLE无数次 然后其实只是因为一个0的判断未跳出

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int inf = 0xffffff;
const int maxn = 1010;
int dp[maxn][maxn][2];      //记录得到当前点最少的2和5的数目
int dir[maxn][maxn][2];     //方向
int num[maxn][maxn][2];     //当前点2和5的数目
int n;
bool mark;
int cnt;

void print(int x, int y, int k);

int main() {
    scanf("%d", &n);
    memset(num, 0, sizeof(num));        //初始化
    memset(dir, 0, sizeof(dir));        //初始化
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < n; ++j) {
            int tmp;
            scanf("%d", &tmp);
            dp[i][j][0] = inf;
            dp[i][j][1] = inf;
            if(tmp == 0) {
                mark = true;
                cnt = i;
                continue;
            }
            while(tmp % 2 == 0) {
                ++ num[i][j][0];
                tmp /= 2;
            }
            while(tmp % 5 == 0) {
                ++ num[i][j][1];
                tmp /= 5;
            }
        }
    }
    dp[0][0][0] = num[0][0][0];
    dp[0][0][1] = num[0][0][1];
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < n; ++j) {
            if(i) {
                if(dp[i][j][0] > dp[i-1][j][0] + num[i][j][0]) {
                    dp[i][j][0] = dp[i-1][j][0] + num[i][j][0];
                    dir[i][j][0] = 0;
                }
                if(dp[i][j][1] > dp[i-1][j][1] + num[i][j][1]) {
                    dp[i][j][1] = dp[i-1][j][1] + num[i][j][1];
                    dir[i][j][1] = 0;
                }
            }
            if(j) {
                if(dp[i][j][0] > dp[i][j-1][0] + num[i][j][0]) {
                    dp[i][j][0] = dp[i][j-1][0] + num[i][j][0];
                    dir[i][j][0] = 1;
                }
                if(dp[i][j][1] > dp[i][j-1][1] + num[i][j][1]) {
                    dp[i][j][1] = dp[i][j-1][1] + num[i][j][1];
                    dir[i][j][1] = 1;
                }
            }
        }
    }
    int k = dp[n-1][n-1][0] > dp[n-1][n-1][1] ? 1 : 0;
    if(mark && dp[n-1][n-1][k] > 1) {
        puts("1");
        for(int i = 1; i <= cnt; ++i) {
            printf("D");
        }
        for(int i = 1; i < n; ++i) {
            printf("R");
        }
        for(int i = cnt+1; i < n; ++i) {
            printf("D");
        }
        puts("");
    }
    else {
        printf("%d\n", dp[n-1][n-1][k]);
        print(n-1, n-1, k);
        puts("");
    }

    return 0;
}

void print(int x, int y, int k) {           //递归输出
    if(x == y && y == 0) {
        return ;
    }
    if(dir[x][y][k] == 0) {
        print(x-1, y, k);
        printf("D");
    }
    else if(dir[x][y][k] == 1) {
        print(x, y-1, k);
        printf("R");
    }
}

C. Commentator problem
time limit per test
1 second
memory limit per test
64 megabytes
input
standard input
output
standard output

The Olympic Games in Bercouver are in full swing now. Here everyone has their own objectives: sportsmen compete for medals, and sport commentators compete for more convenient positions to give a running commentary. Today the main sport events take place at three round stadiums, and the commentator's objective is to choose the best point of observation, that is to say the point from where all the three stadiums can be observed. As all the sport competitions are of the same importance, the stadiums should be observed at the same angle. If the number of points meeting the conditions is more than one, the point with the maximum angle of observation is prefered.

Would you, please, help the famous Berland commentator G. Berniev to find the best point of observation. It should be noted, that the stadiums do not hide each other, the commentator can easily see one stadium through the other.

Input

The input data consists of three lines, each of them describes the position of one stadium. The lines have the format x,  y,  r, where (x, y) are the coordinates of the stadium's center ( -  103 ≤ x,  y ≤ 103), and r (1 ≤ r  ≤ 103) is its radius. All the numbers in the input data are integer, stadiums do not have common points, and their centers are not on the same line.

Output

Print the coordinates of the required point with five digits after the decimal point. If there is no answer meeting the conditions, the program shouldn't print anything. The output data should be left blank.

Examples
input
0 0 10
60 0 10
30 30 10
output
30.00000 0.00000

题目链接:http://codeforces.com/contest/2/problem/C

题解:三个圆 不相交 然后求一个点到三个点的视角和最大

模拟退火算法 这里用到一个小技巧就是估价函数视角的和的选取 用距离/半径 然后视角和用距离/半径的差的平方的和来代替 精度到一定范围就可以得出答案 这道题是随机算法求解的所以一定注意精度

PS:这道题拖了好久一直不想碰 因为觉得模拟退火理解的不够 好吧其实就是这几天比较懒 

AC代码:

#include <bits/stdc++.h>
using namespace std;
struct Circle {
    double x, y, r;
};
const int dy[4] = {-1, 0, 0, 1};
const int dx[4] = {0, -1, 1, 0};
double ang[3];
Circle c[3];
double K(double x) {
    return x * x;
}

double Dis(double x, double y, double xx, double yy) {
    return sqrt(K(x - xx) + K(y - yy));
}

double Val(double x, double y) {            //估价函数
    for(int i = 0; i < 3; ++i) {
        ang[i] = Dis(x, y, c[i].x, c[i].y) / c[i].r;
    }
    double val = 0;
    for(int i = 0; i < 3; ++i) {
        val += K(ang[i] - ang[(i+1) % 3]);
    }
    return val;
}

int main() {
    double x = 0, y = 0;
    for(int i = 0; i < 3; ++i) {
        scanf("%lf%lf%lf", &c[i].x, &c[i].y, &c[i].r);
        x += c[i].x / 3;
        y += c[i].y / 3;
    }

    //模拟退火
    double err = Val(x, y);
    double step = 1;
    for(int tim = 1; tim < 1e5; ++tim) {
        bool flag = false;
        double X, Y;
        for(int i = 0; i < 4; ++i) {
            double xx = x + dx[i] * step;
            double yy = y + dy[i] * step;
            double val = Val(xx, yy);
            if(val < err) {
                err = val;
                flag = true;
                X = xx;
                Y = yy;
            }
        }
        if(flag) {
            x = X;
            y = Y;
        }
        else {
            step /= 2;
        }
    }

    if(err < 1e-6) {
        printf("%.5f %.5f\n", x, y);
    }
    return 0;
}




猜你喜欢

转载自blog.csdn.net/u012431590/article/details/51503456