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;
}