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;
}
posted @ 2022-04-03 13:33  PHarr  阅读(42)  评论(0编辑  收藏  举报