2016郑州大学ACM/ICPC训练赛 Round1

A 强迫症走一波

传送门

直接计算v的二进制中1的个数就行了(貌似是某场cf的一道题)

#include <bits/stdc++.h>
#define ll long long
#define N 1010
using namespace std;
int main()
{
#ifndef ONLINE_JUDGE
//  freopen("1.txt", "r", stdin);
#endif
    ll t, n , ans;
    cin >> n;
    while(n--) 
    {
        cin >> t;
        ans = 0;
        while(t)
        {
            ans += t%2;
            t >>= 1;
        }
        cout << ans << endl;
    }
    return 0;
}

B 优惠券

传送门

直接重载一下<就行了,然后排序一下

#include <bits/stdc++.h>
#define ll long long
#define N 1010
using namespace std;
struct node{
    ll a, b;
    friend bool operator < (node aaa, node bbb)
    {
        if (aaa.a == bbb.a) return aaa.b > bbb.b;
        return aaa.a < bbb.a;
    }
}aa[N];
int main()
{
#ifndef ONLINE_JUDGE
    freopen("1.txt", "r", stdin);
#endif
    ll n, k, i;
    while(cin >> n >> k)
    {
        for (i = 0; i < n; i++)
            cin >> aa[i].a >> aa[i].b;
        sort(aa, aa+n);
        for (i = n-1; i >= 0; i--)
        {
            if (aa[i].b >= k)
                cout << aa[i].a << " " << aa[i].b << endl;
        }
    }
    return 0;
}

C 魔法花园

传送门
比赛的时候我直接暴力,然后加上一堆break就过了

#include <bits/stdc++.h>
#define ll long long
#define N 210
using namespace std;
char mm[N][N];
int x, y;
int fun(int x1, int y1, int x2, int y2)
{
    for (int i = x1; i <= x2; i++)
    {
        if (mm[i][y1] == 'X' || mm[i][y2] == 'X')   return -1;
//      if ( mm[i][y2] == 'X')  return -2;
    }
    for (int i = y1; i <= y2; i++)
    {
        if (mm[x1][i] == 'X' || mm[x2][i] == 'X')   return -1;
//      if (mm[x2][i] == 'X')   return -4;
    }

    return (x2-x1+1)*(y2-y1+1);
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("1.txt", "r", stdin);
#endif
    int i1, i2, j1, j2, k, n, m, ans, s1, s2;
    bool flag; 
    while(cin >> n >> m)
    {
        for (int i = 0; i < n; i++)
            cin >> mm[i];
        ans = 0;
        for (i1 = 0; i1 < n; i1++)
        {

            for (j1 = 0; j1 < m; j1++)
            {
                flag = false;
                for (s2 = j1; s2 < m; s2++)
                    if (mm[i1][s2] == 'X')  break;
                for (s1 = i1; s1 < n; s1++)
                    if (mm[s1][j1] == 'X')  break;
                for (i2 = s1 - 1; i2 >= i1; i2--)
                {
                    for (j2 = s2 - 1; j2 >= j1; j2--)
                    {
                        if (flag)
                        {
                            if ((x-i2)*(y-j1+1) < (j2-y)*(i2-i1+1))
                            {
                                k = fun(i1, j1, i2, j2);
                                if (k != -1)
                                {
//                                  cout << i1 << ' ' << j1 << ' ' << i2 << ' ' << j2 << ' ' << k << endl;
                                    ans = max(ans, k);
                                    x = i2;
                                    y = j2;
                                    break;
                                }
                            }
                            else    break;

                        }
                        k = fun(i1, j1, i2, j2);
                        if (k != -1)
                        {
//                          cout << i1 << ' ' << j1 << ' ' << i2 << ' ' << j2 << ' ' << k << endl;
                            ans = max(ans, k);
                            x = i2;
                            y = j2;
                            flag = true;
                            break;
                        }
                    }
                }
            }
        }
        cout << ans << endl;
    }
    return 0;
}

然而标程是这样的
先求二维前缀和
然后先遍历长方形的两个竖着的边,然后在遍历长方形的上边。
当last为-1 的时候表示还没找到长方形的上边,
当last不等于-1时,last的值就是当前已经找到的上边

#include <stdio.h>
#include <string.h>
char mm[210][210];
int a[210][210];
int main()
{
    int n, m, i, j, k, ans;
    while(scanf("%d%d", &n, &m) != EOF)
    {
        for (i = 1; i <= n; i++)
            scanf("%s", mm[i]+1);
        memset(a, 0, sizeof(a));
        for (i = 1; i <= n; i++)
        {
            for (j = 1; j <= m; j++)
            {
                a[i][j] = a[i-1][j]+a[i][j-1]-a[i-1][j-1];
                if (mm[i][j] == 'X')
                {
                    a[i][j]++;
                }
            }
        }
        int last = -1, t, ans = 0;
        for (i = 1; i <= m; i++)
        {
            for (j = i; j <= m; j++)
            {
                last = -1;
                for (k = 1; k <= n; k++)
                {
                    if (mm[k][j] == 'X' || mm[k][i] == 'X') 
                    {
                        last = -1;
                        continue;
                    }
                    t = a[k][j]-a[k][i-1]-a[k-1][j]+a[k-1][i-1];
                    if (!t)
                    {
                        if (last == -1)
                        {
                            if (ans < j-i+1)    ans = j-i+1;
                            last = k;
                        }
                        else
                        {
                            if (ans < (j-i+1)*(k-last+1))   ans = (j-i+1)*(k-last+1);
                        }
                    }
                }
            }
        }
        printf("%d\n", ans);
    }
    return 0;
} 

这个一个学长的做法
暴力+dp判断是否能够构成边框

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

#define MAX_N 210

int ans;
int n,m;
char strMap[MAX_N][MAX_N];

int l[MAX_N][MAX_N];
int u[MAX_N][MAX_N];
int r[MAX_N][MAX_N];
int d[MAX_N][MAX_N];

bool IsOK(int x,int y,int w,int h)
{
    int lx,ly;

    lx=x-w+1;
    ly=y-h+1;

    if(r[ly][lx]>=w && l[y][x]>=w && d[ly][lx]>=h && u[y][x]>=h) return true;

    return false;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        ans=0;
        memset(strMap,0,sizeof(strMap));
        for(int i=1;i<=n;i++) scanf("%s",&strMap[i][1]);
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(strMap[i][j]=='X')
            {
                l[i][j]=0;
                u[i][j]=0;
            }
            else
            {
                l[i][j]=l[i][j-1]+1;
                u[i][j]=u[i-1][j]+1;
            }
        }
        for(int i=n;i>=1;i--)
        for(int j=m;j>=1;j--)
        {
            if(strMap[i][j]=='X')
            {
                r[i][j]=0;
                d[i][j]=0;
            }
            else
            {
                r[i][j]=r[i][j+1]+1;
                d[i][j]=d[i+1][j]+1;
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                int k,l;
                for(k=1;k+i-1<=n;k++) if(strMap[i+k-1][j]=='X') break;
                for(l=1;l+j-1<=m;l++) if(strMap[i][l+j-1]=='X') break;
                for(int ii=k-1;ii>=1;ii--)
                for(int jj=l-1;jj>=1;jj--)
                {
                    if(IsOK(j+jj-1,i+ii-1,jj,ii))
                    {
                        ans=max(ans,jj*ii);
                        break;
                    }
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值