[Offer收割]编程练习赛31

H星人社交网络

题解

题目很简单,注意的是浮点数处理和相关的判断没写错就可以了,这种题目一般两种思路:
一个是前缀和,一个是取尺法

代码(前缀和)

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
const int MAXN = 1e6 + 5;
typedef long long LL;
int N;
LL A[MAXN], S[MAXN];
int main() {
    while(~scanf("%d", &N)) {
        memset(S, 0, sizeof(S));
        for(int i = 0; i < N; i ++) {
            scanf("%lld", &A[i]);
            S[A[i]] ++;
        }
        for(int i = 1; i < MAXN; i ++) {
            S[i] += S[i - 1];
        }
        LL ret = 0;
        for(int i = 0; i < N; i ++) {
            //printf("[[%d]]\n", i);
            double l = A[i] / 8. + 8;
            int lt = ceil(l);
            int r = A[i] * 8 + 8;
            if(A[i] < 88888 && r > 88888) r = 88888;
            if(r >= lt)
                ret += S[r] - S[lt - 1];
            if(A[i] >= lt && A[i] <= r) ret --;
        }
        printf("%lld\n", ret);
    }
    return 0;
}

代码(取尺法)

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
const int MAXN = 1e6 + 5;
typedef long long LL;
int N;
LL A[MAXN];
int main() {
    while(~scanf("%d", &N)) {
        for(int i = 0; i < N; i ++) {
            scanf("%lld", &A[i]);
        }
        sort(A, A + N);
        int l = 0, r = -1;
        LL ret = 0;
        for(int i = 0;i < N;i ++){
            while(l < N && A[l] * 8< A[i] + 64) l ++;
            while(r < N && A[r] <= A[i] * 8 + 8 && (A[i] >= 88888 || A[i] < 88888 && A[r] <= 88888)) r++;
             r --;
            //printf("%d, %d\n", l, r);
            if(r >= l) ret += r - l + 1;
            if(i >= l && i <= r) ret --;
        }
        printf("%lld\n", ret);
    }
    return 0;
}

Jerry的奶酪

题解

这道题目涉及到了最短路,状态压缩和动态规划吧,状态压缩针对的对象很简单,就是针对K,因为范围在[0,10],去掉不必要的东西,将所有的奶酪建成一张图,然后再图上跑状压即可。

代码

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
#include <cmath>
#include <queue>
using namespace std;
const int MAXN = 3e2 + 5;
const int MAXM = 10 + 5;
const int INF = 0x3f3f3f3f;
typedef long long LL;
int N, M, K;

char MP[MAXN][MAXN];
int d[MAXM][MAXM];
bool vis[MAXN][MAXN];
int S[MAXM][1 << MAXM];
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
vector<pair<int,int> > vp;
struct O{
    int x;
    union{
        int y;
        int bit;
    };
    int s;
    O(int x, int y, int s):x(x), y(y), s(s){}
    bool operator < (const O &p) const{
        return bit > p.bit;
    }
};

int bfs(int s, int t) {
    memset(vis, false, sizeof(vis));
    queue<O> Q;
    while(!Q.empty()) Q.pop();
    Q.push(O(vp[s].first, vp[s].second, 0));
    vis[vp[s].first][vp[s].second] = true;
    while(!Q.empty()) {
        O p = Q.front();
        Q.pop();
        if(MP[p.x][p.y] == '1') return INF;
        if(vp[t].first == p.x && vp[t].second == p.y) return p.s;
        //if(x == N - 1 && y == M - 1) return;
        for(int i = 0; i < 4; i ++) {
            int nx = p.x + dx[i];
            int ny = p.y + dy[i];
            if(nx < 0 || nx >= N || ny < 0 || ny >= M || MP[nx][ny] == '1' || vis[nx][ny]) continue;
            vis[nx][ny] = true;
            Q.push(O(nx, ny, p.s + 1));
        }
    }
    return INF;
}

void bfs2(int s, int t){
    memset(S, 0x3f, sizeof(S));
    priority_queue<O> Q;
    while(!Q.empty()) Q.pop();
    Q.push(O(s, 1 << s, 0));
    S[s][1 << s] = 0;
    while(!Q.empty()){
        O p = Q.top();
        Q.pop();
        if(S[p.x][p.bit] < p.s) continue;
        S[p.x][p.bit] = p.s;
        for(int i = 0;i <= K + 1;i ++){
            if(d[p.x][i] == INF || p.x == i) continue;
            Q.push(O(i, p.bit | 1 << i, p.s + d[p.x][i]));
        }
    }

}

int main() {
    while(~scanf("%d%d%d", &N, &M, &K)) {
        for(int i = 0; i < N; i ++) {
            scanf("%s", MP[i]);
        }
        int x, y;
        int v = -1;
        vp.clear();
        for(int i = 0; i < K; i ++) {
            scanf("%d%d", &x, &y);
            MP[x][y] = v --;
            vp.push_back(make_pair(x, y));
        }

        if(MP[0][0] != '1')MP[0][0] = v --;
        if(MP[N - 1][M - 1] != '1')MP[N - 1][M - 1] = v --;
        vp.push_back(make_pair(0, 0));
        vp.push_back(make_pair(N - 1, M - 1));
        memset(d, 0x3f, sizeof(d));


        for(int i = 0; i < MAXM; i ++) d[i][i] = 0;
        for(int i = 0; i < vp.size(); i ++) {
            for(int j = 0;j < vp.size();j ++){
                 d[i][j] = d[j][i] = bfs(i, j);
            }
        }

        bfs2(K, K + 1);
        printf("%d\n", S[K + 1][(1 << K + 2) - 1] == INF ? -1 : S[K + 1][(1 << K + 2) - 1]);
    }
    return 0;
}

/*
5 5 3
01000
01010
00010
01010
00001
0 4
2 2
4 0
*/

数组分拆II

题解

贪心+动态规划

代码

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 1e5 + 5;
const int mod = 1e9 + 7;
int b[MAXN];
int p[MAXN];
int l[MAXN], r[MAXN];
int N;
int A[MAXN];
int pre_p[MAXN];
LL S[MAXN];
LL f[MAXN];
int main() {
    while(~scanf("%d", &N)) {
        memset(pre_p, 0, sizeof(pre_p));
        memset(b, 0, sizeof(b));
        memset(l, 0, sizeof(l));
        memset(r, 0, sizeof(r));
        memset(S, 0, sizeof(S));
        for(int i = 1; i <= N; i ++) {
            scanf("%d", &A[i]);
        }
        int l_p = 0;
        for(int i = 1; i <= N; i ++) {
            if(pre_p[A[i]] >= l_p) {
                b[i] = b[i - 1] + 1;
                l_p = i;
                l[b[i]] = r[b[i]]= i;
                r[b[i] - 1] = i - 1;
            }
            else b[i] = b[i - 1];
            p[i] = max(p[i - 1], pre_p[A[i]]);
            pre_p[A[i]] = i;
            r[b[i]] = i;
        }
        f[0] = S[0] = 1;
        for(int i = 1; i <= N; i ++) {
            int t = max(p[i], l[b[i] - 1]) - 1;
            LL tv = 0;
            if(t >= 0) tv = S[t];
            f[i] = ((S[min(i - 1, r[b[i] - 1])] - tv) % mod + mod) % mod;
            S[i] = (S[i - 1] + f[i]) % mod;
        }
        printf("%d %lld\n", b[N], f[N] % mod);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值