AtCoder Beginner Contest 218

AtCoder Beginner Contest 218

  • A和B是纯纯的水题,就不说了

C - Shapes

思路分析
  • 昨天这场C题题意一直没搞懂,最后猜题意做出来的,我猜出来的意思就是可以旋转一圈,然后带’#'的要整体平移、但是好像看官方题解并不是这样的。就很奇怪,但是我猜的这个意思又A了,就很奇怪,然后这场C题题意不太清楚。最后还是说一下我怎么实现的吧。
  • 首先我是暴力做的,我把每一个’#‘的 x , y x,y x,y记录下来,然后把每次顺时针旋转90的位置也记录下来,最后只要有一种旋转后的结果中’#'的相对 x , y x,y x,y之差相同即输出Yes,否则输出No。代码写的有点乱(因为这题卡了好久所以有点裂),其实很好实现的,也算个水题吧,但是他这个题目意思真的阴间
代码如下
#include <bits/stdc++.h>
using namespace std;
const int N = 201;
struct node
{
        int x, y;
} a[N * N], a1[N * N], a2[N * N], a3[N * N], a4[N * N], t[N * N];
//储存#的位置
int cnt1 = 0;
int cnt2 = 0;
bool cmp(node a, node b)
{
        if (a.x == b.x)
                return a.y < b.y;
        return a.x < b.x;
}
int main()
{
        int n;
        cin >> n;
        for (int i = 1; i <= n; i++)
        {
                for (int j = 1; j <= n; j++)
                {
                        char ch;
                        cin >> ch;
                        if (ch == '#')
                        {
                                a[++cnt1].x = i;
                                a[cnt1].y = j;
                        }
                }
        }
        for (int i = 1; i <= cnt1; i++)
        {
                a1[i].y = n - a[i].x + 1;
                a1[i].x = a[i].y;
        }
        //90
        sort(a1 + 1, a1 + 1 + cnt1, cmp);
        for (int i = 1; i <= cnt1; i++)
        {
                a2[i].y = n - a1[i].x + 1;
                a2[i].x = a1[i].y;
        }
        //180
        sort(a2 + 1, a2 + 1 + cnt1, cmp);
        for (int i = 1; i <= cnt1; i++)
        {
                a3[i].y = n - a2[i].x + 1;
                a3[i].x = a2[i].y;
        }
        //270
        sort(a3 + 1, a3 + 1 + cnt1, cmp);
        for (int i = 1; i <= n; i++)
        {
                for (int j = 1; j <= n; j++)
                {
                        char ch;
                        cin >> ch;
                        if (ch == '#')
                        {
                                t[++cnt2].x = i;
                                t[cnt2].y = j;
                        }
                }
        }
        if (cnt1 != cnt2)
        {
                cout << "No" << endl;
                return 0;
        }
        bool flag1 = 0, flag2 = 0, flag3 = 0, flag4 = 0;
        //
        int absx = abs(a1[1].x - t[1].x), absy = abs(a1[1].y - t[1].y);
        for (int i = 2; i <= cnt1; i++)
        {
                if ((absx != abs(a1[i].x - t[i].x)) || (absy != abs(a1[i].y - t[i].y)))
                {
                        flag1 = 1;
                }
                else
                        continue;
        }
        if (!flag1)
        {
                cout << "Yes" << endl;
                return 0;
        }
        //
        absx = abs(a2[1].x - t[1].x), absy = abs(a2[1].y - t[1].y);
        for (int i = 2; i <= cnt1; i++)
        {
                if ((absx != abs(a2[i].x - t[i].x)) || (absy != abs(a2[i].y - t[i].y)))
                {
                        flag2 = 1;
                }
                else
                        continue;
        }
        if (!flag2)
        {
                cout << "Yes" << endl;
                return 0;
        }
        absx = abs(a3[1].x - t[1].x), absy = abs(a3[1].y - t[1].y);
        for (int i = 2; i <= cnt1; i++)
        {
                if ((absx != abs(a3[i].x - t[i].x)) || (absy != abs(a3[i].y - t[i].y)))
                {
                        flag3 = 1;
                }
                else
                        continue;
        }
        if (!flag3)
        {
                cout << "Yes" << endl;
                return 0;
        }
        absx = abs(a[1].x - t[1].x), absy = abs(a[1].y - t[1].y);
        for (int i = 2; i <= cnt2; i++)
        {
                if ((absx != abs(a[i].x - t[i].x)) || (absy != abs(a[i].y - t[i].y)))
                {
                        flag4 = 1;
                }
                else
                        continue;
        }
        if (!flag4)
        {
                cout << "Yes" << endl;
                return 0;
        }
        cout << "No" << endl;
        return 0;
}

D - Rectangles

思路分析:
  • 题目的意思就是问能找到多少对点(四个点)能组成长方形,当时想着就是暴力能不能过,结果还是tle了,看了下题解,原来对于vector可以直接二分(二分返回值是bool型),所以我们就直接先sort一下我们储存的坐标,然后 O ( n 2 ) O(n^2) O(n2)找一个左下角的点和右上角的点,然后用二分查找一下是否有左上角和右下角的点即可。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int main()
{
        int n;
        cin >> n;
        vector<pair<int, int>> v(n);
        for (int i = 0; i < n; i++)
                cin >> v[i].first >> v[i].second;
        sort(v.begin(), v.end());
        int ans = 0;
        for (int i = 0; i < n; i++)
                for (int j = 0; j < n; j++)
                        if (v[i].first < v[j].first && v[i].second < v[j].second)
                        {
                                if (binary_search(v.begin(), v.end(), make_pair(v[i].first, v[j].second)) && binary_search(v.begin(), v.end(), make_pair(v[j].first, v[i].second)))
                                        ans++;
                        }
        cout << ans << endl;
}

E - Destruction

思路分析
  • 题目先给我们一个图,然后要我们去删边,使得他最后依然连通。结果要求删的边的边权加起来最大,相信很多人看到这个题目就知道是一个最小生成树的题吧,但是这题有坑,就是我们用 K r u s k a l Kruskal Kruskal做的话,如果我们把最小生成树构造出来了,但是还有负边权的边。因为如果我们选择删除这些负边权的边的话,我们就得不到最大值,所以那些负边无需拿出来
  • 那么我的实现方法还是很笨的,就是我在读入的时候就把边标记为 0 0 0,表示没有用到(指构造最小生成树的时候),那么在用 K r u s k a l Kruskal Kruskal后再循环一下所有边,如果那条边没有被用来构造并且他的边权是正数,我们就 a n s + 边 权 ans+边权 ans+
  • 当然这题还有其他方法,我暂时还没想到,刚刚看到的有一个是,先直接把负边权的边连上,然后构造最小生成树,我没去做,就不知道是否可行了。
代码如下
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e6 + 10;
struct edge
{
        int u, v;
        bool vis;
        ll w;
} edges[maxn];
int fa[maxn];
int n, m;
void init()
{
        for (int i = 1; i <= n; i++)
        {
                fa[i] = i;
        }
}
int find(int x)
{
        return fa[x] == x ? x : fa[x] = find(fa[x]);
}
bool cmp(edge a, edge b)
{
        return a.w < b.w;
}
void kruscal()
{
        for (int i = 1; i <= m; i++)
        {
                int fu = find(edges[i].u), fv = find(edges[i].v);
                if (fu != fv)
                {
                        if (fu > fv)
                                swap(fu, fv);
                        fa[fv] = fu;
                        edges[i].vis = 1;
                }
                else
                        continue;
        }
}
int main()
{
        scanf("%d %d", &n, &m);
        init();
        for (int i = 1; i <= m; i++)
        {
                scanf("%d %d %lld", &edges[i].u, &edges[i].v, &edges[i].w);
        }
        sort(edges + 1, edges + 1 + m, cmp);
        kruscal();
        ll ans = 0;
        for (int i = 1; i <= m; i++)
        {
                if (edges[i].vis == 0 && edges[i].w >= 0)
                {
                        ans += edges[i].w;
                }
        }
        printf("%lld", ans);
        return 0;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值