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;
}

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