Educational Codeforces Round 89(A-C) A数学, B 区间更新, c贪心。(19退役场,以后慢慢做吧,欲速则不达(速度的提升还是要靠经验的积累和码速))

A. Shovels and Swords

在这里插入图片描述

题意:

给你stick(棍)和diamonds的个数。
要你转换成shovel(铁铲)或swords
shovel 需要 2* stick 1* diamondsword 需要 1* stick 2* diamond
要你把他们卖掉,卖掉shovelswords都可以得到1 * emerald(绿宝石)
题目给你stickdiamond数,问你最多有多少个绿宝石。

思路:

其实就是2,1分配的问题。
每次操作都是2,1分配到 两个容器里(容器即stick和diamond,而题目给的stick数和diamond数,就是容器的上限)。
把问题转换成:最多操作几次,直到容器装不下了。

先贪心

最多进行(s+d)/3 (因为每次操作都要2,1即三个空间,不管它往哪边放,反正最好是全放完)。
可是上面贪心是不严谨的
假如s,d为10, 1 按照上述贪心,ans应该是3,但是ans是1.
所以最后的答案ans,还要和s,d之中最小那个比较。
x=min(s,d),y=max(s,d)。
cout<<min(x,(x+y)/3)。

反思

做的时候,贪心不严谨,1wa,其实这道题,我的贪心漏洞很容易发现。
以后打cf记住一句化就行了**“稳中求胜”**

AC

#include <iostream>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        int a,b;
        cin>>a>>b;
        int minx=min(a,b);
        if(a==0||b==0)cout<<0<<endl;
        else cout<<min((a+b)/3,minx)<<endl;
    }
    return 0;
}

B. Shuffle

在这里插入图片描述
在这里插入图片描述

题意:

给你一个初始为1的位置,问你经过m次操作后,最多有几个位置是1(每次操作可以自己和自己换)

思路:

区间更新,先找到包含x的区间(l,r),之后遇到和(l,r)相交的区间就更新 l=min(l,a),r=max(r,b)
这里可能取区间交时,条件有点多,可以取下对立情况。(详见ac1ac2

反思

对于特判没想好,其实题目已经明确了,特判是原封不动即1,(我却傻傻的输出0,哎,直接如土了)

AC1

#include <iostream>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        int a,b,n,flag=0,l=0,r=1e9+10,m,x;
        cin>>n>>x>>m;
        For(i,1,m)
        {
            cin>>a>>b;
            if(!flag&&a<=x&&x<=b)
            {
                flag=1;
                l=a;r=b;
            }
            else if(flag&&( (b<=r&&b>=l) || (a>=l&&a<=r)||(a<=l&&b>=r) ))
            {
                l=min(l,a);
                r=max(r,b);
            }
        }
        if(r==1e9+10)cout<<1<<endl;//我原本输出0,3wa
        else cout<<r-l+1<<endl;
    }
    return 0;
}

AC2(条件压缩版)

#include <iostream>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        int n,m,x,a,b;
        cin>>n>>x>>m;
        int l=x,r=x;
        For(i,1,m)
        {
            cin>>a>>b;
            if(b<l||a>r)continue;//取相反的条件,直接太麻烦了
            l=min(a,l);
            r=max(b,r);
        }
        cout<<r-l+1<<endl;
    }
    return 0;
}

C. Palindromic Paths

在这里插入图片描述
在这里插入图片描述

题意:

本题其实问改变最少,使得所有路径都是对称的,就是画对角线。

思路&&反思:

  1. 注意取对称,对这个矩形图,画对角线(每条对角线为可能的步数),由题意得,对角线上的点应该相等(满足每条路径上的那一步都相等),
  2. 题目还要求前后对称,就是 左上的对角线上的值 要和 右下的对角线的值 相等。

AC

#include <iostream>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
int a[40][40],ans=0;
int n,m,sj;
void check(int x, int y)
{
    int cnt0=0,cnt1=0,i=x,j=y;
    while(i>0&&i<=n&&j>0&&j<=m)
    {
        if(a[i][j]==1)cnt1++;
        else cnt0++;
        if(a[n-i+1][m-j+1]==1)cnt1++;//对称的那条对角线
        else cnt0++;
        i++,j--;
    }
    ans+=min(cnt1,cnt0);
}
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        sj=(n+m+1)/2;
        ans=0;
        For(i,1,n)For(j,1,m)cin>>a[i][j];
        int x=1,y=1;
        For(i,1,sj-1)
        {
            check(x,y);//cout<<ans<<endl;
            if(i<m)y++;//注意对角线的画法
            else x++;
        }
        cout<<ans<<endl;
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章