题意:现在有n张卡片(n <= 16), 每一轮你可以执行两种操作中的一种。1:获得一张红色令牌和一张蓝色令牌。2:购买一张卡片(如果可以买的话),购买的时候蓝色卡片可以充当蓝色令牌,红色同理,但是购买后只消耗令牌,不消耗卡片。问最少多少轮可以购买全部卡片。

思路1:状压DP。我们发现卡片可以减少令牌的使用,如果不考虑卡片的话,总花费其实是固定的。所以,只要我们算出了通过令牌最多可以减免多少花费,就可以得到答案了。

设dp[i][j]为卡片的够买状态为i时,其中红色卡片的花费减免了j,蓝色卡片花费最多减免了多少,直接转移就可以了。求答案时,暴力枚举红色卡牌的减免来更新答案。

代码:

#include <bits/stdc++.h>
#define pii pair<int, int>
using namespace std;
int ans = 1e9, sum1, sum2, mx1, mx2;
char ch[10];
pii a[20];
int dp[1 << 16][260], sum[1 << 16][2], b[20];
int main() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%s%d%d", ch, &a[i].first, &a[i].second);
sum1 += a[i].first, sum2 += a[i].second;
b[i] = (ch[0] == 'B');
}
for (int i = 0; i < (1 << n); i++) {
for (int j = 0; j < n; j++) {
if((i >> j) & 1) {
if(b[j] == 0) sum[i][0]++;
else sum[i][1]++;
}
}
}
memset(dp, -1, sizeof(dp));
dp[0][0] = 0;
for (int i = 0; i < (1 << n); i++) {
for (int j = 0; j < 240; j++) {
if(dp[i][j] == -1) continue;
for (int k = 0; k < n; k++) {
if((i >> k) & 1) continue;
int tmp3 = (i | (1 << k));
int tmp1 = min(sum[i][0], a[k].first), tmp2 = min(sum[i][1], a[k].second);
dp[tmp3][j + tmp1] = max(dp[tmp3][j + tmp1], dp[i][j] + tmp2);
}
}
}
int now = (1 << n) - 1;
for (int i = 0; i < 240; i++) {
if(dp[now][i] == -1) continue;
ans = min(ans, max(sum1 - i, sum2 - dp[now][i]) + n);
}
printf("%d\n", ans);
}

思路2:模拟退火。偶然发现300iq大神当年打这场比赛这题用的模拟退火,我们相当于是对购买的序列进行退火。要注意一点,随着退火的温度降低,活性也要降低,即随机的次数要降低,不能直接random_shuffle了事。

这次是真模拟退火,不是爬山,要跳出局部最优解。

代码:

#include <bits/stdc++.h>
#define db double
#define LL long long
using namespace std;
db T0 = 1000, eps = 1e-3;
int n;
mt19937 random(time(0));
struct node {
char ch;
int x, y;
node(char ch, int x, int y) : ch(ch), x(x), y(y) {}
node() {}
};
vector<node> a, b;
db get() {
LL x = random() + 1, y = random() + 1;
x %= y;
return (db) x / y;
}
int solve() {
int sum1 = 0, sum2 = 0, r = 0, b = 0, ans = 0;
for (int i = 0; i < n; i++) {
int cost = max(max(0, a[i].x - r - sum1), max(0, a[i].y - b - sum2));
sum1 = sum1 + cost - max(0, a[i].x - r);
sum2 = sum2 + cost - max(0, a[i].y - b);
ans += cost;
if(a[i].ch == 'R') r++;
else b++;
}
return ans + n;
}
int main() {
int x, y, ans = 1e9;
char ch[10];
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%s%d%d", ch, &x, &y);
a.push_back(node{ch[0], x, y});
}
random_shuffle(a.begin(), a.end());
db temp = T0;
while(1) {
if(temp < eps) break;
int tmp = solve();
b = a;
//random_shuffle(a.begin(), a.end());
for (int i = 0; i < n * temp / T0; i++){
swap(a[random() % n], a[random() % n]);
}
int tmp1 = solve();
if(tmp1 < tmp) {
tmp = tmp1;
} else {
db change = exp(-(tmp1 - tmp) / temp);
if(get() > change) a = b;
else tmp = tmp1;
}
ans = min(ans, tmp);
temp *= 0.99999;
}
printf("%d\n", ans);
}

  

Codeforces 745E Hongcow Buys a Deck of Cards 状压DP / 模拟退火的更多相关文章

  1. Codeforces 744C Hongcow Buys a Deck of Cards 状压dp (看题解)

    Hongcow Buys a Deck of Cards 啊啊啊, 为什么我连这种垃圾dp都写不出来.. 不是应该10分钟就该秒掉的题吗.. 从dp想到暴力然后gg, 没有想到把省下的红色开成一维. ...

  2. codeforces 744C Hongcow Buys a Deck of Cards

    C. Hongcow Buys a Deck of Cards time limit per test 2 seconds memory limit per test 256 megabytes in ...

  3. Codeforces 744C. Hongcow Buys a Deck of Cards(状压DP)

    这题的难点在于状态的设计 首先显然是个状压,需要一维表示卡的状态,另一维如果设计成天数,难以知道当前的钱数,没法确定是否能够购买新的卡,如果设计成钱数,会发现状态数过多,空间与时间都无法承受.但是可以 ...

  4. Codeforces Round #385 (Div. 1) C. Hongcow Buys a Deck of Cards

    地址:http://codeforces.com/problemset/problem/744/C 题目: C. Hongcow Buys a Deck of Cards time limit per ...

  5. Codeforces Beta Round #8 C. Looking for Order 状压dp

    题目链接: http://codeforces.com/problemset/problem/8/C C. Looking for Order time limit per test:4 second ...

  6. Codeforces 453B Little Pony and Harmony Chest:状压dp【记录转移路径】

    题目链接:http://codeforces.com/problemset/problem/453/B 题意: 给你一个长度为n的数列a,让你构造一个长度为n的数列b. 在保证b中任意两数gcd都为1 ...

  7. Codeforces 1383C - String Transformation 2(找性质+状压 dp)

    Codeforces 题面传送门 & 洛谷题面传送门 神奇的强迫症效应,一场只要 AC 了 A.B.D.E.F,就一定会把 C 补掉( 感觉这个 C 难度比 D 难度高啊-- 首先考虑对问题进 ...

  8. Hongcow Buys a Deck of Cards CodeForces - 744C (状压)

    大意: n个红黑卡, 每天可以选择领取一块红币一块黑币, 或者买一张卡, 第$i$张卡的花费红币数$max(r_i-A,0)$, 花费黑币数$max(b_i-B,0)$, A为当前红卡数, B为当前黑 ...

  9. 「CF744C」Hongcow Buys a Deck of Cards「状压 DP」

    题意 你有\(n\)个物品,物品和硬币有\(A\),\(B\)两种类型,假设你有\(M\)个\(A\)物品和\(N\)个\(B\)物品 每一轮你可以选择获得\(A, B\)硬币各\(1\)个,或者(硬 ...

随机推荐

  1. Ubuntu18.04安装Tensorflow1.14GPU

    软件要求 必须在系统中安装以下 NVIDIA® 软件: https://www.pytorials.com/how-to-install-tensorflow-gpu-with-cuda-10-0-f ...

  2. 拓展练习:Linux权限管理--基础权限/ 特殊权限

    目录 基础权限拓展练习 特殊权限拓展练习 基础权限拓展练习 1.用户基础权限为9位,每三位为一组,每组代表着谁的权限? 前三位代表属主权限位 中间三位代表属组权限位 后三位代表其他用户权限位 2.权限 ...

  3. 【Java学习笔记】百度面试问题回顾(一)

    今天回顾了部分百度面试时被问到的问题: 1.常见的包装类有哪些,他们与基本类型的区别,有哪些方法? Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,这在实际使用时存在很 ...

  4. Spring整合Struts2的两种方式

    https://blog.csdn.net/cuiyaoqiang/article/details/51887594

  5. RFCN理解,不完整待补全

    RFCN的核心是通过修改roi pooling的位置,来增加共享参数的层,减少运算时间: roi pooling位置的影响如下: 越靠近 Input - 对应 ROI-Wise 检测子网越深,准确度也 ...

  6. 数据结构---Java---String

    1.概述 1.1 源码(JDK1.8) public final class String implements java.io.Serializable, Comparable<String& ...

  7. Delphi ini文件结构简介

    一.INI文件的结构:; 注释[小节名]关键字=值 INI文件允许有多个小节,每个小节又允许有多个关键字, “=”后面是该关键字的值. 值的类型有三种:字符串.整型数值和布尔值.其中字符串存贮在INI ...

  8. 查询qq登陆状态

    function qq_status(){ if (empty($qq))$qq = 287959133; $url = 'http://wpa.qq.com/pa?p=2:'.$qq.':52'; ...

  9. 使用JAVA如何对图片进行格式检查以及安全检查处理

    一.通常情况下,验证一个文件是否图片,可以通过以下三种方式: 1).判断文件的扩展名是否是要求的图片扩展名 这种判断是用得比较多的一种方式,不过这种方式非常的不妥,别人稍微的把一个不是图片的文件的扩展 ...

  10. SCP-bzoj-3309

    项目编号:bzoj-3309 项目等级:Safe 项目描述: 戳这里 特殊收容措施: 以下用\((x, y)\)表示\(gcd(x, y)\). \[ ans = \sum _ {i = 1} ^ { ...