Codeforces Round #687 (Div. 2

A. Prison Break

传送门Go

题意:

有一个n*m的监狱,每一个格子有一个犯人,坐标为( r , c )的格子有一条逃生通道,犯人每一秒可以向相邻的且有人的一个格子移动,移动方向为上下左右,问所有犯人到达逃生通道最久需要多少秒。

in put:代表3种情况,m,n,r,c

3
10 10 1 1
3 5 2 4
10 2 5 1

out put:

18
4
6

注意不可以斜着走,所以只需要考虑四个角的犯人用的时间最多的即可。
而这四个角都是(r,c)到相邻两条边的距离,所以只需要找到(r,c)到两条边的最大值即可

#include<bits/stdc++.h>
using namespace std;
int main(){
    int t,a,b,c,d;
    scanf("%d",&t);
    while (t--){
        int m,n;
        scanf("%d%d%d%d",&a,&b,&c,&d);
        m = max(a - c, c-1);
        n = max(b - d, d-1);
        printf("%d\n",m+n);
    }
    return 0;
}

B - Repainting Street

传送门

题意:

有n个房子,1-n排成一列,每个房子有自己初始颜色ci。画家每次可以画连续的k个房子,可以画成任意颜色,或者不变。问最少画几次可以使所有的房子都变成一样的颜色。

颜色只有100种,1e5个房子,直接暴力跑,枚举每种颜色就可以

#include<bits/stdc++.h>
using namespace std;
int a[100006] ,b[106];
int main(){
    int t,n,k,ans,sum;
    scanf("%d",&t);
    while (t--){
        ans = 0x7fffffff;
        scanf("%d%d",&n,&k);
        for (int i = 0; i < n; i++) {
            scanf("%d",&a[i]);
            b[a[i]] = 1;
        }
        for (int i = 1; i < 101; ++i) {
            sum = 0;
            if(b[i]){
                for (int j = 0; j < n; j++) {
             if(a[j] != i) sum++,j+=(k-1);
                }
                ans = min(ans,sum);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

C - Bouncing Ball:

传送门

题意:

n个平台,平台标记为1时,可以使小球弹起来,小球必须从第p个位置开始,而且每次都会向右弹k个单位,标记为0的不可以弹小球,你可以花费x标记为1,也可以删除前几个单位,每个单位花费y,问最少花费多少使得小球能够弹出平台外

因为每k次一个轮回,i和i+k是相关的,所以利用后缀和求出dp数组,然后对每一种可以删除的数量进行遍历,找到最小值
用dp数组记录,从后向前遍历。
dp[i]表示从i开始弹球(i前的删除),改变标记所需要的花费

#include <bits/stdc++.h>
using namespace std;
const int inf = 0x7fffffff;
char s[100006];
int dp[100006];
signed main() {
    int t,x,y,n,p,k,sum;
    scanf("%d",&t);
    while (t--){
        memset(dp,0,sizeof(dp));
        scanf("%d%d%d",&n,&p,&k);
        scanf("%s",s+1);
        scanf("%d%d",&x,&y);
        for (int i = n; i > 0; --i) {
            if(n - i >= k) dp[i] = dp[i+k];//每k个一个轮回
            if(s[i] == '0') dp[i]+=x;
        }
        //dp数组为从后向前遍历的,
        //表示从i开始弹球(i前的删除),所需要的花费
        sum = inf;
        for (int i = p; i <= n; ++i) {
            sum = min(sum, dp[i] + y*(i-p));
        }
        printf("%d\n",sum);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值