Vegetable Chicken Contest Round 2
阿新 • • 發佈:2022-04-03
比例簡化
這道題看似很複雜但是因為資料範圍很少,所以可以直接列舉分子分母按照題目要求選擇即可
#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; }