Educational Codeforces Round 71 (Rated for Div. 2)

Posted vikyanite

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 71 (Rated for Div. 2)相关的知识,希望对你有一定的参考价值。

A. There Are Two Types Of Burgers

水题。题意:给你面包片数,两种不同的肉饼数(制作一个汉堡要消耗两片面包和一片肉饼),之后再给你两种不同的汉堡售价,问你如何取得最大收益。

思路:照题意模拟即可 ,简单贪心。

技术图片
#include <iostream>
#include <sstream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;
 
int main()

    int t;
    scanf("%d", &t);
    while (t--)
    
        int b, p, f;
        int h, c;
        cin >> b >> p >> f;
        cin >> h >> c;
        if (h > c)
        
            int sum = 0;
            while (b >= 2 && p)
                sum += h, b -= 2, p--;
            while (b >= 2 && f)
                sum += c, b -= 2, f--;
            cout << sum << endl;
        
        else
        
            int sum = 0;
            while (b >= 2 && f)
                sum += c, b -= 2, f--;
            while (b >= 2 && p)
                sum += h, b -= 2, p--;
            cout << sum << endl;
        
    
View Code

B. Square Filling

算是水题吧。但是当时我想不出来(我还是太菜了wwww),还去问了子巨(子巨tql)。

暴力枚举判断即可。

题意:你有一个0矩阵。问你是否能经过操作变成题目给你的矩阵。

思路:枚举矩阵的每一个点。之后依次turn(将周围变成1),之后check是否与给出矩阵相符。若不符则turn_back,符合则压入vector。

注意的是可能存在都为0的情况,所以在最开始读入矩阵时,要加入flag判断是否题目给出的是0矩阵。

技术图片
#include <iostream>
#include <sstream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;
int n, m;
int cnt;
int sample[51][51];
int temp[51][51];
int tmp[2][2];
vector <int> ans;
int final_check()
    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) if (temp[i][j] != sample[i][j]) return 1;
    return 0;

void turn_back(int x, int y)
    for (int i = x; i <= x + 1; i++)
        for (int j = y; j <= y + 1; j++)
            temp[i][j] = tmp[i-x][j-y];


void turn(int x, int y)
    for (int i = 0; i <=  1; i++)
        for (int j = 0; j <= 1; j++)
            tmp[i][j] = temp[x+i][y+j];

    for (int i = x; i <= x + 1; i++)
        for (int j = y; j <= y + 1; j++)
            temp[i][j] = 1;
            if (temp[i][j] != sample[i][j])
                turn_back(x, y);
                return ;
            
        
    
    cnt++; ans.push_back(x); ans.push_back(y);


int main()

    cin >> n >> m;
    int flag = 0; //判断是否为0矩阵
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            scanf("%d", &sample[i][j]);
            if (sample[i][j]) flag = 1;
        
    for (int i = 0; i < n-1; i++) for (int j = 0; j < m-1; j++) turn(i, j);

    if (!flag) cout << "0" << endl;
    else if (!cnt || final_check()) cout << "-1" << endl;
    else
        cout << cnt << endl;
        for (int i = 0; i < ans.size(); i+=2)
            cout << ans[i]+1 << " " << ans[i+1]+1 << endl;
    
    return 0;
View Code

C. Gas Pipeline(补题)

题意:二进制01串。为1代表这个地方得是高度为2的柱子,为0代表可以为高度为1或者2的柱子。

起点和终点柱子高度都为1。同时横向走的时候需要管道。柱子的单位花费是b,管道的单位花费是a。问怎么安排使得花费最小

思路:这道题有两种思路贪心与DP。

dp:读题不难发现,对于每个地方,要么是低位,要么是高位,影响因素只有花费和1的位置。

易得dp转移方程为  1.dp[i][0]=min(dp[i-1][1]+2*a+b,dp[i-1][0]+a+b);
          2.dp[i][1]=min(dp[i-1][1]+a+2*b,dp[i-1][0]+2*a+2*b);
DP的代码:

技术图片
#include <cstring>
#include <algorithm>
#include <cstdio>
typedef long long ll;
using namespace std;
#define maxn 200000 + 100
char s[maxn];
ll dp[maxn][2];
int main()

    ll n, a, b, t;
    scanf("%lld", &t);
    while (t--)
        scanf("%lld %lld %lld %s", &n, &a, &b, s);
        memset(dp, 0x3f, sizeof(dp));
        dp[0][0] = b; //一开始必然是低位
        for (ll i = 1; i <= n; i++)
            if ((s[i] == 0 && s[i-1] == 0) || i == n)
                dp[i][0] = min(dp[i-1][1] + 2 * a + b, dp[i-1][0] + a + b);
            dp[i][1] = min(dp[i-1][1] + a + 2 * b, dp[i-1][0] + 2 * a + 2 * b);
        
        printf("%lld\n", dp[n][0]);
    
View Code

贪心:如果有n个点的话,就会有n+1个柱子。字符串为1的话,1这个格子代表的两个点都必须是是高柱子。

首先确定基础花费:n个管道:n*a,n+1个低柱子:n*b,2个转折管道:2*a。中间可以高柱子的部分,假设长度为x,选择高柱子,额外花费为x*b。选择低柱子,花费为2*a。选择最小的就可以了。

贪心代码:

技术图片
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#define  maxn  200000 + 10
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;

ll rec_pilar[maxn];
char s[maxn];
int main()
    ll t; scanf("%lld", &t);
    while (t--)
        memset(rec_pilar, 0, sizeof(rec_pilar));
        ll n, a, b;
        scanf("%lld %lld %lld", &n, &a, &b);
        scanf("%s", s);
        //st和ed是用来记录高位的最左边和最右边
        ll st = inf, ed = 0;
        for (ll i = 0; i < n; i++)
            //若s为1的话那么1左右两边的柱子都应该是高位
            if (s[i] == 1)
                rec_pilar[i] = 1;
                rec_pilar[i+1] = 1;
                st = min(st, i);
                ed = max(ed, i + 1);
            
        

        ll num0 = 0,num1 = 0; //num0记录低位,num1记录高位
        ll ans = 0;
        for (ll i = st; i <= ed; i++)
            ll tmp = 0;
            if (rec_pilar[i] == 0) num0++;
            else
                num1++;
                //每次加上贪心结果
                ans += min(num0 * b, 2 * a);
                num0 = 0;
            
        

        ans += 2 * a + n * a + (n + 1) * b + num1 * b;
        //要是一直都是低位
        if (st == inf && ed == 0) ans -= 2 * a;
        printf("%lld\n", ans);
    
    return 0;
View Code

 

以上是关于Educational Codeforces Round 71 (Rated for Div. 2)的主要内容,如果未能解决你的问题,请参考以下文章

Educational Codeforces Round 7 A

Educational Codeforces Round 7

Educational Codeforces Round 90

Educational Codeforces Round 33

Codeforces Educational Codeforces Round 54 题解

Educational Codeforces Round 27