BestCoder Round 50 (div 2)

BestCoder Round 50 (div 2)

1001 Distribution money

  • 题意:给出一串数字,让你找出其中出现次数超过一半的数,找到则输出它,没有则输出-1
  • 思路:一开始看到题,还以为是曾经做过的用栈来解决的那个问题。但是此题不同的是,不能保证一定存在超过一半的数,所以不能直接用那个思路。还有此题的数字个数比较少,并且每个数字的范围是0-10000,所以直接朴素的扫描然后找出就好了,是个大水题。
  • 代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <stack>

using namespace std;

const int maxn = 10000 + 5;
int A[maxn];
int main() {
    int n;
    while(scanf("%d", &n) == 1) {
        memset(A, 0, sizeof(A));
        for(int i = 0; i < n; i++) {
            int num;
            scanf("%d", &num);
            A[num]++;
        }

        int p = 0;
        for(int i = 1; i < maxn; i++) {
            if(A[i] > A[p]) p = i;
        }

        if(A[p] > n / 2) {
            printf("%d\n", p);
        }   else {
            printf("-1\n");
        }
    }
    return 0;
}

1002 Run

  • 题意:直接看官方描述吧

    小花是一个热爱健身的姑娘,这天她下载了一个跑步软件,这个软件可以记录下小花跑步的轨迹。小花决定去公园跑步。公园里有许许多多的座椅,小花希望在一些座椅休息一下,并且她在两条座椅之间只跑直线。小花是一个完美主义者,她希望自己最后的轨迹是一个正三边形或者正四边形或者正五边形或者正六边形。小花会从某条座椅开始打开跑步软件,并在回到这个座椅后关闭。
    请问小花有多少种跑法。注:若两种跑法经过的座椅集合相同则认为是一种跑法。且经过一条座椅时没有必要一定停下来

  • 思路: 还是直接看官方题解吧

    1002 Run
    地球人都知道整点是不能构成正五边形和正三边形和正六边形的,所以只需暴力枚举四个点判断是否是正四边形即可。假如你不是地球人,那么即使暴力枚举正三边形和稍微不那么暴力地找正五边形和正六边形也是可以通过的(反正找不到)。

  • 自己的看法:我只想表示:我真的不是地球人!!

  • 代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 20 + 5;

struct Point{
    int x, y;
    Point(int x = 0, int y = 0):x(x), y(y) {}
    bool operator < (Point b) const {
        return x < b.x || x == b.x && y < b.y;
    }
};

int dist(Point a, Point b) {
    return (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y);
}

bool is_square(vector<Point> &p) {
    sort(p.begin(), p.end());
    Point A = p[0], B = p[1], C = p[2], D = p[3];
    if(dist(A, B) == dist(B, D) &&
       dist(B, D) == dist(D, C) &&
       dist(D, C) == dist(C, A) &&
       dist(C, A) == dist(A, B)) {
        if(dist(A, D) == dist(B, C)) {
            return true;
        }
    }
    return false;
}

Point chairs[maxn];
int main() {
    int n;
    while(cin >> n) {
        memset(chairs, 0, sizeof(chairs));
        for(int i = 0; i < n; i++){
            scanf("%d%d", &chairs[i].x, &chairs[i].y);
        }

        vector<Point> p;
        int ans = 0;
        for(int c1 = 0; c1 < n; c1++)
        for(int c2 = c1 + 1; c2 < n; c2++)
        for(int c3 = c2 + 1; c3 < n; c3++)
        for(int c4 = c3 + 1; c4 < n; c4++) {
            p.clear();
            p.push_back(chairs[c1]);
            p.push_back(chairs[c2]);
            p.push_back(chairs[c3]);
            p.push_back(chairs[c4]);
            if(is_square(p)) ans++;
        }

        printf("%d\n", ans);
    }
    return 0;
}

1003 The mook jong

  • 题意:有一个由1*1的方块组成的1*n的地板,然后在方块上面放木桩,要求相邻两个木桩之间的距离>=2,并且整个地板上至少放一个木桩,问有多少种放法。
  • 思路:一开始想暴力深搜的,因为题目中的n的范围是1-60,但是后来突然想到,这个是可以dp解决的。并且貌似类似的放置数的问题在之前周赛也已经遇到过一道了,都是用dp解决的。 我们定义dp[i][0]表示放到i个方块(方块编号从0开始),且第i个方块不放置木桩时,有多少种放法;同理定义dp[i][1]第i个方块放置木桩是有多少种放法。这样我们就可以找到状态转移方程。因为第i个方块不放置木桩,所以前面放不放木桩都可以,所以dp[i][0] = dp[i-1][0] + dp[i-1][1]。现在来讨论第i个方块放置木桩的情况,当第i个方块放了木桩,所以第i-1个方块和第i-2个方块都不能放木桩,所以dp[i][1] = dp[i-3][0] + dp[i-3][1]。这样状态转移方程就找出来了,但是因为用到了dp[i-3],所以需要人工把前三个状态数找出来。代码写的很清楚了。需要注意的是因为题目要求至少放一个木桩,所以需要减去1,也就是一个都不放的情况。
  • 优化思路:其实定义成二维是我的思考过程,但是仔细观察dp[i][0] = dp[i-1][0] + dp[i-1][1] :(1), dp[i][1] = dp[i-3][0] + dp[i-3][1] :(2)。如果定义DP[i]为放到第i个方块的放置数的话,有dp[i][0] + dp[i][1] = DP[i],所以(1) + (2)就可以得到 DP[i] = DP[i-1] + DP[i - 3]。所以这道题用一维dp也可以解决。
  • 代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>

using namespace std;

const int maxn = 60 + 5;

long long dp[maxn][2];

void initial() {
    dp[0][0] = 1;
    dp[0][1] = 1;
    dp[1][0] = 2;
    dp[1][1] = 1;
    dp[2][0] = 3;
    dp[2][1] = 1;
    for(int i = 3; i < maxn; i++) {
        dp[i][0] = dp[i - 1][0] + dp[i - 1][1];
        dp[i][1] = dp[i - 3][0] + dp[i - 3][1];
    }
}

int main() {
    int n;
    initial();
    while(scanf("%d", &n) == 1) {
        printf("%I64d\n", dp[n - 1][0] + dp[n - 1][1] - 1);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值