您的位置:首页 > 其它

NOIP模拟(10.19)T3 放盒子

2017-10-19 19:20 405 查看
放盒子

题目背景:

10.19 NOIP模拟T3

分析:费用流

这个题,我是真的没有往费用流想······

考场上还出了点问题,明明应该写双关键字排序的····然后我只排了一个关键词····明明有50分的暴力的,挂成了15分······悲剧,下次一定要注意,怎么错都轻松过样例······

这个题,考虑怎么办,显然我们对于每一个盒子要看第一,是否有盒子可以装他,第二,是否可以装下其他盒子,第三,装哪一个盒子,第四,哪一个盒子装它,每一个盒子只能用一次,有没有感觉到什么2333,我们对于每个盒子拆成两个点,为x1,
x2,如果对于两个盒子,x, y, x可以装下y盒子,那么我们从x1向y2连边,流量为1,费用为y盒子的面积(注意是y,就是y),然后从S向所有的第一部分点连边,流量为1,费用为0,从所有第二部分点向T连边,流量为1,费用为0,然后跑一遍最大费用最大流,用总的盒子的面积减去最大费用即可,流量限制满足每个盒子只用一次,选中了的盒子表示它可以被套住,减去费用,正确性合理。

Source:

/*
created by scarlyw
*/
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cctype>
#include <vector>
#include <queue>
#include <map>
#include <set>

inline char read() {
static const int IN_LEN = 1024 * 1024;
static char buf[IN_LEN], *s, *t;
if (s == t) {
t = (s = buf) + fread(buf, 1, IN_LEN, stdin);
if (s == t) return -1;
}
return *s++;
}

/*
template<class T>
inline void R(T &x) {
static bool iosig;
static char c;
for (iosig = false, c = read(); !isdigit(c); c = read()) {
if (c == -1) return ;
if (c == '-') iosig = true;
}
for (x = 0; isdigit(c); c = read()) x = ((x << 2) + x << 1);
if (iosig) x = -x;
}
//*/

const int OUT_LEN = 1024 * 1024;
char obuf[OUT_LEN], *oh = obuf;
inline void write_char(char c) {
if (oh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), oh = obuf;
*oh++ = c;
}

template<class T>
inline void W(T x) {
static int buf[30], cnt;
if (x == 0) write_char('0');
else {
if (x < 0) write_char('-'), x = -x;
for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48;
while (cnt) write_char(buf[cnt--]);
}
}

inline void flush() {
fwrite(obuf, 1, oh - obuf, stdout);
}

///*
template<class T>
inline void R(T &x) {
static bool iosig;
static char c;
for (iosig = false, c = getchar(); !isdigit(c); c = getchar()) {
if (c == -1) return ;
if (c == '-') iosig = true;
}
for (x = 0; isdigit(c); c = getchar()) x = ((x << 2) + x << 1) + (c ^ '0');
if (iosig) x = -x;
}
//*/

const int MAXN = 400 + 10;
const int INF = ~0u >> 2;

int n, final = ~0u >> 1;

struct data {
int l, w;
inline bool operator < (const data &a) const {
return (l == a.l) ? (w < a.w) : (l < a.l);
}
} box[MAXN];

struct node {
int to, w, c, rev;
node(int to = 0, int w = 0, int c = 0, int rev = 0) : to(to), w(w), c(c),
rev(rev) {}
} ;

bool vis[MAXN];

int ans, s ,t, cnt, sum;
std::vector<node> edge[MAXN];

inline void add_edge(int x, int y, int w, int c) {
edge[x].push_back(node(y, w, c, edge[y].size()));
edge[y].push_back(node(x, 0, -c, edge[x].size() - 1));
}

inline void build_graph() {
R(n), cnt = 0;
for (int i = 1; i <= n; ++i) R(box[i].l), R(box[i].w);
std::sort(box + 1, box + n + 1);
for (int i = 1; i <= n; ++i)
if (box[i].l != box[i - 1].l || box[i].w != box[i - 1].w)
box[++cnt] = box[i], ans += box[i].l * box[i].w;
s = 0, t = 2 * cnt + 1;
for (int i = 1; i <= cnt; ++i)
for (int j = 1; j < i; ++j)
if (box[j].w <= box[i].w)
add_edge(i, j + cnt, 1, box[j].l * box[j].w);
for (int i = 1; i <= cnt; ++i)
add_edge(s, i, 1, 0), add_edge(i + cnt, t, 1, 0);
}

inline bool spfa_slf(int s, int t) {
static bool vis[MAXN];
static int dis[MAXN];
static std::deque<int> q;
for (int i = s; i <= t; ++i) vis[i] = false, dis[i] = -INF;
q.push_back(t), dis[t] = 0, vis[t] = true;
while (!q.empty()) {
int cur = q.front();
q.pop_front(), vis[cur] = false;
for (int p = 0; p < edge[cur].size(); ++p) {
node *e = &edge[cur][p];
if (edge[e->to][e->rev].w > 0 && dis[e->to] < dis[cur] - e->c) {
dis[e->to] = dis[cur] - e->c;
if (!vis[e->to]) {
if (!q.empty() && dis[e->to] > dis[q.front()])
q.push_front(e->to), vis[e->to] = true;
else q.push_back(e->to), vis[e->to] = true;
}
}
}
}
for (int i = s; i <= t; ++i)
for (int p = 0; p < edge[i].size(); ++p) {
node *e = &edge[i][p];
e->c += dis[e->to] - dis[i];
}
return sum += dis[s], (dis[s] > -INF);
}

inline int dfs(int cur, int flow, int t) {
if (cur == t) return ans -= sum * flow, flow;
int ret = 0;
vis[cur] = true;
for (int p = 0; p < edge[cur].size(); ++p) {
node *e = &edge[cur][p];
if (e->w > 0 && e->c == 0 && !vis[e->to]) {
int f = dfs(e->to, std::min(flow - ret, e->w), t);
ret += f, e->w -= f, edge[e->to][e->rev].w += f;
if (ret == flow) return flow;
}
}
return ret;
}

inline void cost_flow(int s, int t) {
while (spfa_slf(s, t)) {
do memset(vis, false, sizeof(bool) * (t + 5));
while (dfs(s, INF, t));
}
std::cout << ans;
}

int main() {
// freopen("box.in", "r", stdin);
// freopen("box.out", "w", stdout);
build_graph();
cost_flow(s, t);
return 0;
}

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: