3171: [Tjoi2013]循环格
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 1149 Solved: 727
[ Submit][ Status][ Discuss]
Description
一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子。每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0)。给定一个起始位置(r,c)
,你可以沿着箭头防线在格子间行走。即如果(r,c)是一个左箭头,那么走到(r,c-1);如果是右箭头那么走到(r,c+1);如果是上箭头那么走到(r-1,c);如果是下箭头那么走到(r+1,c);每一行和每一列都是循环的,即如果走出边界,你会出现在另一侧。
一个完美的循环格是这样定义的:对于任意一个起始位置,你都可以i沿着箭头最终回到起始位置。如果一个循环格不满足完美,你可以随意修改任意一个元素的箭头直到完美。给定一个循环格,你需要计算最少需要修改多少个元素使其完美。
Input
第一行两个整数R,C。表示行和列,接下来R行,每行C个字符LRUD,表示左右上下。
Output
一个整数,表示最少需要修改多少个元素使得给定的循环格完美
Sample Input
3 4
RRRD
URLL
LRRR
RRRD
URLL
LRRR
Sample Output
2
HINT
1<=R,L<=15
Source
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
typedef long long LL;
typedef double DL;
const int INF = 2147483647;
const int maxn = 20;
const int maxp = maxn * maxn * 2;
const int maxm = maxp * maxp * 2;
const int d[4][2] = {{-1,0},{1,0},{0,1},{0,-1}};
struct data{
int to,cap,flow,c;
}e[maxm];
vector<int> G[maxp];
int n,m,s,t,tot,tote = -1,ans;
int x[maxn][maxn],y[maxn][maxn];
int pri[300],dis[maxp],a[maxp],pre[maxp],exist[maxp],Q[maxp];
char gra[maxn][maxn];
inline int getint()
{
int ret = 0,f = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
ret = ret * 10 + c - '0',c = getchar();
return ret * f;
}
inline int spfa()
{
memset(a,0,sizeof(a));
memset(pre,0,sizeof(pre));
memset(exist,0,sizeof(exist));
for (int i = 1; i <= tot; i++) dis[i] = INF;
int head = 0,tail = 0;
dis[Q[++tail] = s] = 0;
a[s] = INF;
while (head < tail)
{
int u = Q[++head];
exist[u] = 0;
for (int i = 0; i < G[u].size(); i++)
{
data E = e[G[u][i]];
if (E.cap == E.flow) continue;
if (dis[E.to] > dis[u] + E.c)
{
a[E.to] = min(a[u],E.cap - E.flow);
dis[E.to] = dis[u] + E.c;
pre[E.to] = G[u][i] ^ 1;
if (!exist[E.to])
exist[Q[++tail] = E.to] = 1;
}
}
}
if (!a[t]) return 0;
int now = t;
while (now != s)
{
e[pre[now] ^ 1].flow += a[t];
e[pre[now]].flow -= a[t];
now = e[pre[now]].to;
}
ans += a[t] * dis[t];
return 1;
}
inline void add(int u,int v,int cap,int c)
{
e[++tote] = (data){v,cap,0,c};
G[u].push_back(tote);
e[++tote] = (data){u,cap,cap,-c};
G[v].push_back(tote);
}
inline char getcom()
{
char c = getchar();
while (c != 'U' && c != 'R' && c != 'D' && c != 'L') c = getchar();
return c;
}
int main()
{
pri['U'] = 0; pri['D'] = 1; pri['R'] = 2; pri['L'] = 3;
n = getint(); m = getint();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
x[i][j] = ++tot , y[i][j] = ++tot;
for (int i = 1; i <= n; i++)
y[i][0] = y[i][m] , y[i][m + 1] = y[i][1];
for (int j = 1; j <= m; j++)
y[0][j] = y[n][j] , y[n + 1][j] = y[1][j];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
gra[i][j] = getcom();
s = ++tot; t = ++tot;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
for (int k = 0; k <= 3; k++)
add(x[i][j],y[i + d[k][0]][j + d[k][1]],1,pri[gra[i][j]] != k);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
add(s,x[i][j],1,0);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
add(y[i][j],t,1,0);
while (spfa());
printf("%d",ans);
return 0;
}