AtCoder Beginner Contest 289(A~D)

比赛链接:Sky Inc, Programming Contest 2023(AtCoder Beginner Contest 289) - AtCoder

A - flip

void solve()
{
    string s;
    cin>>s;
    int len = s.size();
    for(int i=0;i<len;i++){
      if(s[i]=='0') cout<<"1";
      else cout<<"0";
    }
 
}

B - V

1~n被分为若干部分,每个部分需要逆序输出。如1 2 3 4 5分成了(1 2 3)和(4 5),那么输出的结果是3 2 1 5 4。用邻接矩阵存储连接在一起的数字,查找时像dfs一样,输出时利用栈的特点实现逆序输出。

vector<int>v[100+5];
bool vis[100+5];
void solve()
{
    int n,m;
    cin>>n>>m;
    while(m--){
        int val;
        cin>>val;
        v[val].push_back(val+1);
        
    }
    for(int i=1;i<=n;i++){
        stack<int>sta;
        if(!vis[i]){
          int now = i;
          sta.push(i);
          while(v[now].size()){
            now = v[now][0];
            sta.push(now);
            vis[now] = true;
          }
          while(!sta.empty()){
            cout<<sta.top()<<" ";
            sta.pop();
          }
        }
    }
}

C - Coverage

看数据量挺小的就用dfs做了,假设有n个集合,从1~n每个集合分为选与不选两种情况,在搜索层数到达n层时检查是否符合题意得出答案。可以利用set的去重功能检查是否包含了1~n的数。  

set<int>se[10+2];
int ans;
int n,m;
void dfs(int u,set<int>check,bool flag)
{
  if(u>m) return ;
  if(flag){
    for(auto it:se[u]){
      check.insert(it);
    }
  }
  if(u==m && check.size()==n) ans++;
  dfs(u+1,check,true);
  dfs(u+1,check,false);
 
}
void solve()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int t;
        cin>>t;
        while(t--){
          int x;
          cin>>x;
          se[i].insert(x);
        }
    }
    set<int>check;
    dfs(1,check,true);
    dfs(1,check,false);
    cout<<ans<<endl;
    
 
}

D - Step Up Robot

上题用了dfs写导致看见这题也想试试dfs+剪枝能不能过,TLE了8个数据,这里不知道怎么用记忆化,那就用dp好了,f[i]表示能否到达第i级阶梯,从头到尾线性滚一边,检查当前位置能不能由上一个位置转移过来,最终时间复杂度为O(n*x),下面那个版本更符合“常规的”写法。

int n,m;
int goal;
const int N = 100010;
int v[10+2];
int f[N];

void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>v[i];
    cin>>m;
    for(int i=1;i<=m;i++){
      int e;
      cin>>e;
      f[e] = -1;
    }
    cin>>goal;
 
    f[0] = 1;
    for(int i=1;i<=goal;i++){
        if(f[i]>=0){
            for(int j=1;j<=n;j++){
              //i-v[j]检查从上一个转移过来的位置 
                if(i-v[j]>=0 && f[i-v[j]]>0){ //可以走到上一个位置并且那个位置没有地雷
                    f[i] = 1; 
                }
              
            }
        }
    }
 
    if(f[goal]>0) puts("Yes");
    else puts("No");
 
}
int n,m;
int goal;
const int N = 100010;
bool track[N];
int v[10+2];
int f[N];


void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>v[i];
    cin>>m;
    for(int i=1;i<=m;i++){
      int e;
      cin>>e;
      track[e] = true;
    }
    cin>>goal;

    f[0] = 1;
    for(int i=1;i<=goal;i++){
        for(int j=1;j<=n;j++){
          if(track[i]) break;
            if( i>=v[j]) f[i] |= f[i-v[j]];
      
        }
    }
    if(f[goal]) puts("Yes");
    else puts("No");
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值