1. 程式人生 > 其它 >Vegetable Chicken Contest Round 2

Vegetable Chicken Contest Round 2

比賽連結

比例簡化

這道題看似很複雜但是因為資料範圍很少,所以可以直接列舉分子分母按照題目要求選擇即可

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

const int N = 1100;
double a , b , r , c , e = 1e9 , l;

int main()
{
    cin >> a >> b >> l;
    for( double i = 1 ; i <= l ; i ++ )
        for( double j = 1 ; j <= l ; j ++ )
        {
            if( __gcd(int(i), int(j)) != 1 ) continue;
            if( i / j < a / b ) continue;
            if( i / j - a / b < e )
                e = i/j - a/b , r = i , c = j ;
        }
    cout << r << ' ' << c << endl;
    return 0;
}

公交換乘

這道題就是模擬一下即可,要注意每次只能使用一張優惠卷,並且使用優惠卷就不能使用現金了

所以首先判斷是否是公交乘,如果就是公交車就要使用優惠卷,要先刪掉過期的優惠卷,然後找到第一個符合條件的優惠卷即可

如果是地鐵就直接加,並存一下優惠卷即可

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

const int N = 1005;
int n , res;
struct Ticket{
    int price , time;
    bool used;
};

vector< Ticket > q;

int read()
{
    int x = 0 , ch = getchar();
    while( ch < '0' || ch > '9' ) ch = getchar();
    while( ch >= '0' && ch <= '9' ) x = (x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x;
}

int main()
{
    n = read();
    for( int op , price , time ; n ; n --  )
    {
        op = read() , price = read() , time = read();
        if( op ){ // 公交
            while( q.begin()->time < time && q.size() ) // 把過期的票刪掉
                q.erase( q.begin() );
            for( auto &it : q )
                if( it.price >= price ){//找到第一張符合條件的優惠卷
                    it.price = price = 0;
                    break;
                }
        }
        else // 地鐵
            q.push_back( { price , time+45, 0 } );
        res += price;
    }
    cout << res << endl;
    return 0;
}

互不侵犯

這是一道狀壓 dp 的模板,用二進位制來表示一行中國王的情況,比如第一,二行的狀態分別是a,b

如果a&b || a&(b<<1) || a & (b>>1)只要有一個滿足的兩行之間就會衝突

可以先用 dfs中搜索一行符合條件的所有狀態

第一行可以是任意符合條件的狀態

從第二行開始,先枚舉出這一行的狀態,再列舉上一行的狀態,然後判斷是否衝突,然後在列舉一下從第一行到當前行的國王總數就可以開始轉移了

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

const int N = 1100;
int n , k;
ll f[15][N][N] , res;
int s[N] , num[N] , tot;
// s[i] 記錄狀態 , num[i]狀態 i 有多少 1 , tot 總的狀態數

void dfs( int cur , int cnt , int step ) // cur , cnt , step = 狀態,1的個數,第幾位
{
    if( step >= n )
    {
        s[++tot] = cur , num[tot] = cnt;
        return;
    }
    dfs( cur , cnt , step+1);// step位不選
    dfs( cur+( 1 << step ) , cnt+1 , step+2 );// step位選
    return;
}

int main()
{
    cin >> n >> k;
    dfs( 0 , 0 , 0 );
    for( int i = 1 ; i <= tot ; i ++ ) // 第一行任意行
        f[1][i][num[i]] = 1;
    for( int i = 2 ; i <= n ; i ++ )
        for( int j = 1 ; j <= tot ; j ++ ) // 列舉第 i 行狀態
            for(int l = 1 ; l <= tot ; l ++ )//列舉第 i-1 狀態
            {
                if( (s[j]&s[l]) || (s[j]&(s[l]<<1)) || (s[j]&(s[l]>>1)) ) continue;
                for( int p = num[j] ; p <= k ; p ++ ) // 列舉 1 到 i 行總的國王數
                    f[i][j][p] += f[i-1][l][p-num[j]]; // 當前行有 num[j] 個國王 前 i-1 行自然有 p-num[i] 個國王
            }
    for( int i = 1 ; i <= tot ; i ++ )
        res += f[n][i][k];
    cout << res << endl;
    return 0;
}