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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章