Atcoder ABC167 B-D (B...C-dfs||bitmasking D-simulate(复习倍增))

B - Easy Linear Programming

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

反思:

简单分类讨论
写这题码太快,漏了一种情况qwq。

AC

#include <iostream>
using namespace std;
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int a,b,c,d;
    cin>>a>>b>>c>>d;
    int ans=0;
    if(d<=a+b)ans=min(a,d);//没考虑这里1wa,可能选不齐a张,所以取小值。
    else ans=a-(d-a-b);
    cout<<ans<<endl;
    return 0;
}

C - Skill Up

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

题意:

给你n种选择,每个选择都有m个权值,且有一个花费c。
最后求最少花费,使得所有m个值都大于等于x。
数据很小直接dfs。

反思:

  1. 这题可以直接dfs,但也可以用bit去枚举。
  2. vector记得是从0开始,别忘了
  3. vector<vector< int > > a(n, vector< int >(m));二维等价于v【n】【m】
  4. vector< int >ans(m);等价于ans【m】

DFS

#include <iostream>
#include <cstring>
#include <vector>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
vector<int>v[20];
int c[20],ans[20];
int n,m,x;
int minx=1e9;
int flag=0;
void dfs(int cur, int sum)
{
    if(cur==n+1)
    {
        //cout<<sum<<endl;
        int cnt=0;
       // For(i,0,m-1)cout<<ans[i]<<' ';
       // cout<<endl<<endl;
        For(i,0,m-1)if(ans[i]>=x)cnt++;
        if(cnt==m)
        {
            flag=1;
            minx=min(sum,minx);
        }
        return;
    }
    For(i,0,m-1)ans[i]+=v[cur][i];
    dfs(cur+1,sum+c[cur]);
    For(i,0,m-1)ans[i]-=v[cur][i];
    dfs(cur+1,sum);
}
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n>>m>>x;
    int temp;
    For(i,1,n)
    {
        cin>>c[i];
        For(j,1,m)
        {
            cin>>temp;
            v[i].push_back(temp);
        }
    }
    dfs(1,0);
    if(flag)cout<<minx<<endl;
    else cout<<-1<<endl;
    return 0;
}

BIT

#include <iostream>
#include <vector>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
vector<int>v[20];
vector<int>c;
//int ans[20];
//vector<vector<int>> a(n, vector<int>(m));二维
int main()
{
    int n,m,x,temp;
    cin>>n>>m>>x;
    For(i,0,n-1)
    {
        cin>>temp;
        c.push_back(temp);
        For(j,0,m-1)
        {
            cin>>temp;
            v[i].push_back(temp);
        }
    }
    int tot=1<<n;
    int flag=1;
    int minx=1e9;
    For(i,0,tot-1)
    {
        flag=1;
        //For(j,0,m-1)ans[j]=0;
        vector<int>ans(m);
        temp=0;
        For(j,0,n-1)
        {
            if(i>>j&1)
            {
                temp+=c[j];
                For(k,0,m-1)ans[k]+=v[j][k];
            }
        }
        For(j,0,m-1)if(ans[j]<x)flag=0;
        if(flag)minx=min(minx,temp);
    }
    if(minx==1e9)cout<<-1<<endl;
    else cout<<minx<<endl;
    return 0;
}

D - Teleporter

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

题意:

给你一个序列,每个位置可以传送到其他位置,求k次传送后,所到达的位置,
由题意可以分析得,最后可能会进入一个循环。

反思

似乎这题有用到倍增的思想,去补补倍增了(做的时候直接模拟了)

#include <iostream>
#include <vector>
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
int a[maxn],n,temp,vis[maxn];
ll k;
vector<int>v1,v2;
int main()
{
    cin>>n>>k;
    For(i,1,n)
    {
        cin>>temp;
        a[i]=temp;
    }
    ll cur=1,cnt1=0,cnt2=0;
    vis[1]=1;cur=a[cur];
    while(1)
    {
        //next=a[cur];
        if(vis[cur]==1)v2.push_back(cur),cnt2++;
        v1.push_back(cur);
        vis[cur]++;
        if(vis[cur]>2)
        {
            v2.pop_back();v1.pop_back();//找到循环节,不要再进队了e
            break;
        }
        cnt1++;
        cur=a[cur];
    }
    //cout<<cnt1<<' '<<cnt2<<endl;
    if(k<=cnt1)cout<<v1[k-1]<<endl;
    else
    {
        //For(i,0,2)cout<<v2[i]<<' ';
       // cout<<endl;
        ll pos=(k-cnt1-1)%cnt2;
        ll ans=v2[pos];
        cout<<ans<<endl;
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章