A题:DFS搜索

直接遍历字符串s,判断是否依次出现过dfs和DFS

#include<bits/stdc++.h>
using namespace std;
int t,n;
string s;
bool st[6];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>t;
    while(t--)
    {
        memset(st,0,sizeof st);
        bool flag1=false;
        bool flag2=false;
        cin>>n;
        cin>>s;
        for(int i=0;i<n;i++)
        {
            if(s[i]=='D') st[0]=true;
            else if(s[i]=='F'&&st[0]==true) st[1]=true;
            else if(s[i]=='S'&&st[0]==true&&st[1]==true)
            {
                st[2]==true;
                flag1=true;
            }
            else if(s[i]=='d') st[3]=true;
            else if(s[i]=='f'&&st[3]==true) st[4]=true;
            else if(s[i]=='s'&&st[3]==true&&st[4]==true)
            {
                st[5]==true;
                flag2=true;
            }
        }
        if(flag1==true) cout<<1<<' ';
        else cout<<0<<' ';
        if(flag2==true) cout<<1<<endl;
        else cout<<0<<endl;
    }
    
}

B题:关鸡

利用mp1存第一行有火的列,mp2存第二行有火的列。再遍历mp1,用flag1,flag2,flag3,flag4标记左右是否堵住,左右是否有火。分类讨论当中间(2,0)有火时的情况,当中间没有火的情况。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int t,n;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>t;
    while(t--)
    {
        int res=0;//答案
        //mp1[-3]=1表示(1,-3)有火,mp2[-3]=1表示(2,-3)有火
        unordered_map<int,int>mp1,mp2;
        //记录左边是否堵住,右边是否堵住,左边是否有火,右边是否有火
        bool flag1=0,flag2=0,flag3=0,flag4=0;
        
        //输入
        cin>>n;
        for(int i=0;i<n;i++)
        {
            int a,b;
            cin>>a>>b;
            if(a==1) mp1[b]=1;
            else mp2[b]=1;
        }
        //遍历mp1
        for(auto x : mp1)
        {
            int a=x.first;
            if(a<0)
            {
                flag3=true;//左边有火
                if(mp2[a]==1||mp2[a-1]==1||mp2[a+1]==1) flag1=true;//左边堵住
            }
            else if(a>0)
            {
                flag4=true;//右边有火
                if(mp2[a]==1||mp2[a-1]==1||mp2[a+1]==1) 
                {
                    flag2=true;//右边堵住
                    //cout<<"here"<<endl;
                }
            }
        }
        for(auto x : mp2)
        {
            if(x.second==1)
            {
                int a=x.first;
                if(a<0)
                {
                    flag3=true;//左边有火
                    if(mp1[a]==1||mp1[a-1]==1||mp1[a+1]==1) flag1=true;//左边堵住
                }
                else if(a>0)
                {
                    flag4=true;//右边有火
                    if(mp1[a]==1||mp1[a-1]==1||mp1[a+1]==1) flag2=true;//右边堵住
                }
            }
        }
        if(mp2[0]==1)//中间堵住
        {
            if(flag1==1&&flag2==1) res=0;//左右都堵住
            else if(mp1[-1]==1&&mp1[1]==1) res=0;//鸡相邻左右都有火
            else if(mp1[-1]==1&&flag2==true) res=0;//左边堵住,鸡相邻右边有火
            else if(mp1[1]==1&&flag1==true) res=0;//右边堵住,鸡相邻左边有火
            //左边堵住,右边堵住,鸡相邻左边有火,鸡相邻右边有火,四种情况其中之一
            else if(mp1[-1]==1||mp1[1]==1||flag1==true||flag2==true) res=1;
            else res=2;//其他情况需在鸡相邻左右加火
        }
        else
        {
            if(flag1==true&&flag2==true) res=0;//左右都堵住
            else if(flag1==true&&flag4==true) res=1;//左边堵住,右边有火
            else if(flag2==true&&flag3==true) res=1;//右边堵住,左边有火
            else if(mp1[-1]==1&&mp1[1]==1) res=1;
            else if(mp1[-1]==1||mp1[1]==1) res=2;
            else if(flag1==true)
            {
                res=2;//左边堵住,右边无火
                
            }
            else if(flag2==true) 
            {
                res=2;//右边堵住,左边无火
                //cout<<"this"<<endl;
            }
            else if(flag3==true&&flag4==true) 
            {
                res=2;//左右都没堵住,但都有火
            }
            else res=3;//其他情况,将鸡相邻左右和下方添加火
        }
        cout<<res<<endl;
    }
}

C题:按闹分配

按照办事时间从小到大排序,总不满意度最小。二分插入位置mid,插入后其前面人员不满意度不变,其后人员每人不满意度都加上tc,插队后总不满意度为sm+(n-x)*tc

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int n,q,tc,t[N];
long long m;
long long sm,sum;
bool check(int x)
{
    long long sc=0;
    sc=sm+(n-x)*tc;//插队后n个人的总不满意度
    if(sc-sm<=m) return true;
    return false;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>q>>tc;
    for(int i=0;i<n;i++)
    {
        cin>>t[i];
    }
    sort(t,t+n);
    for(int i=0;i<n;i++)
    {
        sum+=t[i];
        sm+=sum;//总不满意度之和
    }
    while(q--)
    {
        long long res=0;
        cin>>m;
        int l=0,r=1e5;//二分查找应插队下标
        while(l<r)
        {
            int mid=(l+r)/2;
            if(check(mid)) r=mid;
            else l=mid+1;
        }
        for(int i=0;i<l;i++)//前l个人的时间
        {
            res+=t[i];
        }
        res+=tc;//鸡办事的时间
        cout<<res<<endl;
    }
    
}

E题:这题又使用了贪心

暴力搜索,dfs搜索所有可能情况

#include<bits/stdc++.h>
using namespace std;
int a[15];
pair<int,int>p[15];
int t,n,m,res;
void dfs(int u)
{
    if(u==m+1)//m场比赛完毕
    {
        int t=1;
        for(int i=1;i<=n;i++)
        {
            if(a[i]>a[1]) t++;
        }
        res=min(res,t);
        return;
    }
    int x=p[u].first,y=p[u].second;
    //x号选手赢
    a[x]+=3;
    dfs(u+1);
    a[x]-=3;
    //y号选手赢
    a[y]+=3;
    dfs(u+1);
    a[y]-=3;
    //平局
    a[x]+=1;
    a[y]+=1;
    dfs(u+1);
    a[x]-=1;
    a[y]-=1;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>t;
    while(t--)
    {
        res=15;//最终名次
        cin>>n>>m;
        for(int i=1;i<=n;i++) cin>>a[i];
        for(int i=1;i<=m;i++) 
        {
            int x,y;
            cin>>x>>y;
            p[i].first=x;
            p[i].second=y;
        }
        dfs(1);//遍历k场比赛的结果,取排名最高的赋值给res
        cout<<res<<endl;
    }
}

G题:why外卖

首先处理特殊数据,如果bi大于等于ai的话,相当于白送bi元钱,即m+=bi。其余数据按照ai从大到小排序。用sum存储ai及其后优惠卷的bi总和。接下来遍历ai,假设当前能够使用该优惠卷,则接下来所有的比当前ai小的优惠价都能使用,则此时可用总现金m+sum>=ai。即只要满足m+sum>=ai,则可购买的最大食物原价为m+sum。如果当前不满足m+sum>=ai,则当前优惠卷的bi将无法使用,则更新sum=sum-bi。特判如果遍历所有优惠卷后没有优惠卷可以使用,已有现金m即为可购买的最高原价商品。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
pair<int, int> p[N]; // 存储优惠券信息
int T, n;
long long m;
long long x;
bool cmp(pair<int,int>a , pair<int,int>b)
{
    return a.first>b.first;
}
int main() 
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> T;
    while(T--) 
    {
        cin >> n >> m;
        int cnt=1;
        for(int i = 1; i <= n; i++) 
        {
            int a,b;
            cin>>a>>b;
            if(a>b)
            {
                p[cnt].first=a;
                p[cnt].second=b;
                //cout<<a<<' '<<b<<endl;
                //cout<<cnt<<endl;
                cnt++;
            }
            else 
            {
                m+=b;
            }
        }
        // a[i]从大到小排序
        sort(p+1, p + cnt, cmp);
        long long sum=0;
        for(int i=1;i<=cnt-1;i++)
        {
            sum+=p[i].second;
        }

        bool flag=0;
        //cout<<"sum="<<sum<<endl;
        //cout<<"m="<<m<<endl;
        for(int i = 1; i <=cnt-1; i++) 
        {
            if(m>=p[i].first-sum)
            {
                //cout<<x<<endl;
                x=m+sum;
                flag=1;
                break;
            }
            else
            {
                sum-=p[i].second;
            }
        }
        if(flag==1) cout << x << "\n";
        else cout<<m<<endl;
    }
    return 0;
}

L题:要有光

当光源无限接近x轴时,能使得绿墙w在平面xoy轴上的投影最大,面积为梯形面积2wc

#include<cstdio>
#include<iostream>
#include<iomanip>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<unordered_map>
#include<set>
#include<unordered_set>
#include<vector>
#include<bitset>
#include<deque>
#include<cctype>
#include<bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t=0;
    cin>>t;
    while(t--)
    {
        double c,d,h,w;
        cin>>c>>d>>h>>w;
        cout << fixed << setprecision(6)<< 3*c*w << endl;
    }
}

M题:牛客老粉才知道的密码

起初是A~F,每次向右可以显示下六道题,如果不足六道就显示最后六题。然后从最后六题开始,每次向左可以显示前六题,如果不足六题显示最前面六题,所以如果n是六的倍数,一共有n/6种显示结果,如果n不是6的倍数,从头到尾有n/6+1种显示结果,从尾到头n/6-2种结果(因为首位两者已经被计算过),一共有2*n/6种结果

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

int T;
long long n;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> T;
    while(T--) {
        cin >> n;
        long long result;
        if(n % 6 == 0) {
            // n是6的倍数,直接计算
            result = n / 6;
        } else {
            // n不是6的倍数,计算头尾的不同起始位置
            result = 2 * (n / 6); // 根据新理解修正
        }
        cout << result << endl;
    }
}