QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#555804#4169. 代码拍卖会David_Mercury0 0ms0kbC++142.7kb2024-09-10 10:09:292024-09-10 10:09:30

Judging History

你现在查看的是最新测评结果

  • [2024-09-10 10:09:30]
  • 评测
  • 测评结果:0
  • 用时:0ms
  • 内存:0kb
  • [2024-09-10 10:09:29]
  • 提交

answer

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 20, dx[4] = {0, 0, 1, -1}, dy[4] = {1, -1, 0, 0}, INF = 0x3f3f3f3f;
int n, m, s, t, e = 1, head[MAXN*MAXN*2], w[MAXN*MAXN*2], c[MAXN*MAXN*2], p[MAXN*MAXN*2];
bool inq[MAXN*MAXN*2];
char qwq[MAXN][MAXN];

inline int Trans(char c){
	if(c == 'R')	return 0;
	if(c == 'L')	return 1;
	if(c == 'D')	return 2;
	return 3;
}

struct node{
	int to, ci, wi, nxt;
} edge[MAXN*MAXN*5*2];

inline void Add_edge(int u, int v, int c, int w){
	edge[++e] = (node){v, c, w, head[u]}, head[u] = e;
	edge[++e] = (node){u, 0, -w, head[v]}, head[v] = e;
	return;
}

inline bool EK(){
	for(int i = s; i <= t; i++)	w[i] = INF;
	c[s] = INF, w[s] = p[t] = 0;
	queue<int> que; que.push(s);
	while(!que.empty()){
		int x = que.front(); que.pop();
		inq[x] = false;
		for(int i = head[x]; i; i = edge[i].nxt){
			int to = edge[i].to;
			if(!edge[i].ci)					continue;
			if(w[to] <= w[x]+edge[i].wi)	continue;
			w[to] = w[x]+edge[i].wi;
			c[to] = min(c[x], edge[i].ci);
			p[to] = i;
			if(!inq[to])	que.push(to), inq[to] = true;
		}
	}
	return p[t];
}

inline void Update(){
	for(int i = p[t]; i; i = p[edge[i^1].to])
		edge[i].ci -= c[t], edge[i^1].ci += c[t];
	return;
}

int main(){
	cin>>n>>m;
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)	cin>>qwq[i][j];
	s = 0, t = n*m*2+1;
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++){
			Add_edge(s, (i-1)*m+j, 1, 0);
			Add_edge(n*m+(i-1)*m+j, t, 1, 0);
			for(int k = 0; k < 4; k++){
				int x = i+dx[k], y = j+dy[k];
				if(x < 1)	x = n;
				if(x > n)	x = 1;
				if(y < 1)	y = m;
				if(y > m)	y = 1;
				if(Trans(qwq[i][j]) == k)	Add_edge((i-1)*m+j, n*m+(x-1)*m+y, 1, 0);
				else						Add_edge((i-1)*m+j, n*m+(x-1)*m+y, 1, 1);
			}
		}
	int mincost = 0, maxflow = 0;
	while(EK())	maxflow += c[t], mincost += c[t]*w[t], Update();
	cout<<mincost;
	
	return 0;
}
/*
看数据范围目测是状压 DP 之类的
但是直接状压需要压 4^n 个格子。。。

从图论的角度来说,我们要将一个内向基环树森林变为若干个环
(每个点入度至多为 4)
即每个点入度为 1 出度为 1

感觉上出奇地适配网络流,尝试
可以给每个点连四条出边,每条容量为 1,一条费用为 0 其余费用为 1,并且点拆边限制容量为 1
但是源汇很难设置 
可以跑无源汇上下界可行费用最小流

怎么跑?
强制每条边的下界满流,然后检查每个点是否流量守恒
对于 out > in:说明流入不够,将其与超级汇点连边 out-in
对于 in > out:说明流出不够,将其与超级源点连边 in-out
由于图的特殊性,等价于一个点拆为出入点,然后连接成一个二分图最小带权完美匹配 
*/

详细


Pretests


Final Tests

Test #1:

score: 0
Runtime Error

input:

982 473

output:


result:


Test #2:

score: 0
Time Limit Exceeded

input:

82749201374821543 5

output:


result:


Test #3:

score: 0
Time Limit Exceeded

input:

17327482917364121 7

output:


result:


Test #4:

score: 0
Time Limit Exceeded

input:

28489124728192763 1

output:


result:


Test #5:

score: 0
Time Limit Exceeded

input:

40285729174762941 25

output:


result:


Test #6:

score: 0
Time Limit Exceeded

input:

999999 499

output:


result:


Test #7:

score: 0
Time Limit Exceeded

input:

58390378572931426 113

output:


result:


Test #8:

score: 0
Time Limit Exceeded

input:

38475729495732951 491

output:


result:


Test #9:

score: 0
Time Limit Exceeded

input:

71937591037847128 487

output:


result:


Test #10:

score: 0
Time Limit Exceeded

input:

100000000000000000 491

output:


result: