codeforces 1221 A B C D

传送门

A 2048

题意:multiset里面有许多2的幂,每次可以从multiset取出两个一样的数字,放回去两数之和,问能否出现2048.

分析:优先队列模拟操作

B knights

题意:棋子可以走日字,将n*n的棋盘用W与B填满,代表两个阵营的棋子,使得可以互相攻击的点对数量最大。

分析:大水题

  解法一:

  bfs,在左上角先放一个棋子,然后在可以攻击到的地方放敌对棋子,然后重复直到没有格子可以填。

  解法二:
  棋子与他可以攻击到的位置的曼哈顿距离为奇数,所以构造棋盘使得不存在相邻的B与W即可,就像国际象棋的棋盘。

C Perfect Team

题意:c,m,x代表coder,mathematician,和咸鱼,一只队伍必须要有一个coder和mathematician,必须要有三个人,求最多队伍数。

分析:解法一:不考虑人数配置,队伍数为(c+m+x)/3,考虑人数配置,将这个值跟c和m三个值取最小值即为答案。

解法二:比较容易想到,先组出c,m,x各一个的队伍,对于剩下来的人,二分可以组出的队伍数量,加上前面的结果就是答案。

D Make The Fence Great Again

题意:给定数组a和b,ai是第i元素的值,bi是将ai+1的代价,求最小代价,使得a中没有相邻的元素相同。

分析:首先,很容易想到对于每一个元素只需要+0,+1或+2就可以使得a满足条件。

令dp[i][j]为第i位上升j的合法情况的最小代价,如果a[i]==a[i-1],那么dp[i][0]为第i位上升0合法的最小代价,如果ai上升0,ai-1的合法状态为上升1或者2,所以dp[i][0]可以从dp[i-1][1]和dp[i-1][2]转移,dp[i][1]可以从dp[i-1][0]和dp[i-1][2]转移。依次类推。

这道题比赛时如果用cin不关同步可以过样例,但是赛后会被hack。

#include <bits/stdc++.h>
#define mp make_pair
#define mst(a,n) memset(a, n, sizeof(a))
#define debug(x) cout << #x << ": " << x << endl
#define pb push_back
typedef long long LL;
const int maxn = 3e5 + 10;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
using namespace std;
LL n, q, a[maxn], b[maxn], dp[maxn][3];
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> q;
    while (q--) {
        cin >> n;
        for (int i = 0; i < n; ++i) {
            cin >> a[i] >> b[i];
        }
        LL ans = 0;
        for (int i = 0; i < n; ++i)
            dp[i][0] = 0;
        dp[0][1] = b[0];
        dp[0][2] = 2 * b[0];
        for (int i = 1; i < n; ++i) {
            if (a[i] == a[i - 1]) {
                dp[i][0] = min(dp[i - 1][1], dp[i - 1][2]);
                dp[i][1] = min(dp[i - 1][0], dp[i - 1][2]) + b[i];
                dp[i][2] = min(dp[i - 1][1], dp[i - 1][0]) + b[i] * 2;
            }
            else if (a[i] == a[i - 1] + 1) {
                dp[i][0] = min(dp[i - 1][0], dp[i - 1][2]);
                dp[i][1] = min(dp[i - 1][0], dp[i - 1][1]) + b[i];
                dp[i][2] = min(dp[i - 1][0], min(dp[i - 1][1], dp[i - 1][2])) + b[i] * 2;
            }
            else if (a[i] == a[i - 1] - 1) {
                dp[i][0] = min(dp[i - 1][0], min(dp[i - 1][1], dp[i - 1][2]));
                dp[i][1] = min(dp[i - 1][1], dp[i - 1][2]) + b[i];
                dp[i][2] = min(dp[i - 1][0], dp[i - 1][2]) + b[i] * 2;
            }
            else if (a[i] == a[i - 1] + 2) {
                dp[i][0] = min(dp[i - 1][0], dp[i - 1][1]);
                dp[i][1] = dp[i][0] + b[i];
                dp[i][2] = dp[i][0] + b[i] * 2;
            }
            else if (a[i] == a[i - 1] - 2) {
                dp[i][0] = min(dp[i - 1][0], min(dp[i - 1][1], dp[i - 1][2]));
                dp[i][1] = dp[i][0] + b[i];
                dp[i][2] = min(dp[i - 1][1], dp[i - 1][2]) + b[i] * 2;
            }
            else {
                dp[i][0] = min(dp[i - 1][0], min(dp[i - 1][1], dp[i - 1][2]));
                dp[i][1] = dp[i][0] + b[i];
                dp[i][2] = dp[i][0] + b[i] * 2;
            }
        }
        cout << min(dp[n - 1][0], min(dp[n - 1][1], dp[n - 1][2])) << endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值