[Offer收割]编程练习赛4

本文解析了四道编程题的解题思路与AC代码实现,包括Playfair密码表的模拟实现、修补木桶问题的二分查找解决方案、图像算子问题的高斯消元法求解及奖券兑换问题的多重背包算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Playfair密码表

题目链接:

http://hihocoder.com/problemset/problem/1361

解题思路:

模拟即可。

AC代码:

#include<bits/stdc++.h>
using namespace std;

const int N = 30;
int vis[N];
char output[N];

int main(){
    string str;
    while(cin>>str){
        memset(vis,0,sizeof(vis));
        int len = str.size();
        for(int i = 0; i < len; ++i){
            if(str[i] == 'J')
                str[i] = 'I';
        }
        int l = 0;
        for(int i = 0; i < len; ++i){
            if(!vis[str[i]-'A'])
                output[l++] = str[i];
            vis[str[i]-'A'] = 1;
        }
        for(int i = 0; i < 26; ++i){
            if(!vis[i] && i != 9)
                output[l++] = 'A'+i;
        }
        for(int i = 0; i < 25; ++i){
            printf("%c",output[i]);
            if(i%5 == 4)
                puts("");
        }
    }
    return 0;
}

修补木桶(二分)

题目链接:

http://hihocoder.com/problemset/problem/1362

解题思路:

二分答案,枚举起点。

AC代码:

#include<bits/stdc++.h>
using namespace std;

const int N = 1005;
int n,m,L;
int a[N];

int solve(int x){
    int num = 0;
    for(int i = 0; i < n; ++i){
        if(a[i] < x){
            ++num;
            i += L-1;
        }
    }
    return num;
}

int main(){
    while(~scanf("%d%d%d",&n,&m,&L)){
        for(int i = 0; i < n; ++i)
            scanf("%d",&a[i]);
        int l = 0,r = 1e9+7;
        while(l <= r){
            int mid = (l+r)/2;
            int num = 10000;
            for(int i = 0; i < L; ++i){
                for(int j = 0; j < n-1; ++j)
                    swap(a[j],a[j+1]);
                num = min(num,solve(mid));
            }
            if(num <= m) l = mid+1;
            else r = mid-1;
        }
        printf("%d\n",r);
    }
    return 0;
}

图像算子(高斯消元)

题目链接:

http://hihocoder.com/problemset/problem/1363

解题思路:

解线性方程组,高斯消元。

AC代码:

#include<bits/stdc++.h>
#define eps 1e-9
using namespace std;

const int N = 105;
const int M = 10005;
int h,w,d;
int a[N][N];
int b[N][N];
double Mat[M][M];
double V[M];

void Gasse(int n,int m){
    int i,j,k = 0;
    for(j = 0; j < m; ++j){
        for(i = k; i < n; ++i){
            if(fabs(Mat[i][j]) > eps)
                break;
        }
        if(i == n)
            continue;

        for(int p = 0; p < m; ++p)
            swap(Mat[i][p],Mat[k][p]);
        swap(V[i],V[k]);

        double tmp = Mat[k][j] ;
        for(int p = j; p < m; ++p)
            Mat[k][p] /= tmp;
        V[k] /= tmp;

        for(int p = 0; p < n; ++p){
            if(p!=k && (fabs(Mat[p][j])>eps)){
                tmp = Mat[p][j];
                for(int q = 0; q < m; ++q)
                    Mat[p][q] -= tmp*Mat[k][q];
                V[p] -= tmp*V[k];
            }
        }
        ++k;
    }
}

int main(){
    while(~scanf("%d%d%d",&h,&w,&d)){
        for(int i = 0; i < h; ++i){
            for(int j = 0; j < w; ++j){
                scanf("%d",&a[i][j]);
                }
        }
        for(int i = 0; i < h-d+1; ++i){
            for(int j = 0; j < w-d+1; ++j){
                scanf("%d",&b[i][j]);
            }
        }
        int r = 0;
        for(int i = 0; i < h-d+1; ++i){
            for(int j = 0; j < w-d+1; ++j){
                for(int p = 0; p < d; ++p){
                    for(int q = 0; q < d; ++q){
                        Mat[r][p*d+q] = a[i+p][j+q];
                    }
                }
                V[r] = b[i][j];
                r++;
            }
        }
        Gasse(r,d*d);
        for(int i = 0; i < d*d; ++i){
            if(i%d != 0)
                printf(" ");
            if(V[i] > -1e-6)\
                printf("%.0f",(V[i]+1e-6));
            else
                printf("%.0f",(V[i]-1e-6));
            if(i%d == d-1)
                printf("\n");
        }
    }
    return 0;
}

奖券兑换(多重背包)

题目链接:

http://hihocoder.com/problemset/problem/1364

解题思路:

二进制优化背包

AC代码:

#include<bits/stdc++.h>
using namespace std;

const int N = 100005;
map<pair<int,int>,int> mp;
int dp[N];

int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        int need,value;
        for(int i = 1; i <= n; ++i) {
            scanf("%d%d",&need,&value);
            ++mp[make_pair(need,value)];
        }
        vector<pair<pair<int,int>,int> > v(mp.begin(),mp.end());
        for(int i = 0; i < (int)v.size(); ++i){
            int num = v[i].second;
            need = v[i].first.first;
            value = v[i].first.second;
            for(int k = 1; num > 0; k <<= 1) {
                int mul = min(k,num);
                for(int j = m; mul * need <= j; --j) {
                    dp[j] = max(dp[j],dp[j-mul*need] + mul*value);
                }
                num -= mul;
            }
        }
        int ans = *max_element(dp, dp+m+1);
        printf("%d\n", ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值