日程表
【题目描述】
热情的选手 Sphinny 正在看新一年的日程表,并发现已经安排了很多编程竞赛。她将这一年的每一天都用以下三种方式之一在日程表上打标记。
1. 白色:这一天她将不参加竞赛。或许这一天没有预定的竞赛,或许
这一天有更重要的事情要做(生活中肯定还有其他美好的事情) 。
2. 蓝色:这一天她将参加一场竞赛。
3. 问号:这一天有预定好的竞赛,但她还没有决定好是否参加。
为了简化问题,我们假设没有资格的概念:你不必参加一场比赛去取得另一场比赛的参赛资格。
Sphinny 生活的世界与我们的世界有所不同,那个世界里一年有 n 个月每个月恰有 m 天。看她美丽的日程表。Sphinny 认为对于每一天,有四天与它相邻(可能有的不存在):同一个月的前一天,同一个月的后一天,前一个月的同一天,后一个月的同一天。Sphinny 想最大化所有竞赛的喜悦值之和。一场竞赛的喜悦值的计算方式是:
1. 初始为 4。
2. 每有与那一天相邻的一天要参赛,喜悦值减 1。 (你可以认为
Sphinny 喜欢竞赛,但连续参赛让她感觉很累。并且出于审美的原因,在相邻两个月的同一天参赛也不是很好。 )
现在,Sphinny 想计划这一年,并决定把每一个问号标记都改为白色标记或蓝色标记。她的目标很简单,就是最大化总喜悦值。
【输入格式】
第一行一个整数 T 表示测试数据组数。
对于每一组数据:第一行两个整数 n,m 表示有 n 个月,每个月有 m 天。之后 n 行每行一个长度为 m 的字符串,第 i 行第 j 个字符表示第 i 个月的第 j天的状态, “#”表示这一天被标记为蓝色, “.”表示这一天被标记为白色,“?”表示这一天被标记为问号。
【输出格式】
对于每一组数据,输出:
Case #X: Y
X 是第几组测试数据,Y 是最大总喜悦值。
【输入样例】
2
3 3
.?.
.?.
.#.
5 8
.#...##.
.##..?..
.###.#.#
??#..?..
###?#...
【输出样例】
Case #1: 8
Case #2: 42
【数据范围】
对于 30%的数据,1≤n,m≤5
对于 60%的数据,1≤n,m≤15
对于 100%的数据,1≤n,m≤50,1≤T≤100
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define N 1000003
#define M 103
#define inf 1000000000
using namespace std;
int n,m,tot;
int map[M][M],vis[M][M],cnt;
int point[N],next[N],v[N],remain[N],last[N],cur[N],num[N];
int deep[N],belong[M][M];
int xx[10]={0,1,0,-1},yy[10]={1,0,-1,0};
void add(int x,int y,int z)
{
tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=z;
//cout<<x<<" "<<y<<" "<<z<<endl;
tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0;
}
int addflow(int s,int t)
{
int now=t;
int ans=inf;
while(now!=s)
{
ans=min(ans,remain[last[now]]);
now=v[last[now]^1];
}
now=t;
while(now!=s)
{
remain[last[now]]-=ans;
remain[last[now]^1]+=ans;
now=v[last[now]^1];
}
return ans;
}
void dfs(int s,int t)
{
for (int i=s;i<=t;i++) deep[i]=t;
deep[t]=0;
queue<int> p; p.push(t);
while(!p.empty())
{
int now=p.front(); p.pop();
for (int i=point[now];i!=-1;i=next[i])
if (remain[i^1]&&deep[v[i]]==t)
deep[v[i]]=deep[now]+1,p.push(v[i]);
}
}
int isap(int s,int t)
{
dfs(s,t);
for (int i=s;i<=t;i++) cur[i]=point[i];
for (int i=s;i<=t;i++) num[deep[i]]++;
int now=s; int ans=0;
while(deep[s]<t)
{
if (now==t)
{
ans+=addflow(s,t);
now=s;
}
bool f=false;
for (int i=cur[now];i!=-1;i=next[i])
if (deep[v[i]]+1==deep[now]&&remain[i])
{
f=true;
last[v[i]]=i;
cur[now]=i;
now=v[i];
break;
}
if (!f)
{
int minn=t;
for (int i=point[now];i!=-1;i=next[i])
if (remain[i]) minn=min(minn,deep[v[i]]);
if (!--num[deep[now]]) break;
deep[now]=minn+1;
num[deep[now]]++;
cur[now]=point[now];
if (now!=s)
now=v[last[now]^1];
}
}
return ans;
}
int calc(int x,int y)
{
int sum=0;
for (int i=0;i<4;i++)
{
int nowx=x+xx[i];
int nowy=y+yy[i];
if (nowx>0&&nowy>0&&nowx<=n&&nowy<=m&&map[nowx][nowy]!=1)
sum++;
}
return sum;
}
int calc2(int x,int y)
{
int sum=0;
for (int i=0;i<4;i++)
{
int nowx=x+xx[i];
int nowy=y+yy[i];
if (nowx>0&&nowy>0&&nowx<=n&&nowy<=m&&map[nowx][nowy]==1)
sum++;
}
return sum;
}
int main()
{
freopen("cal.in","r",stdin);
freopen("cal.out","w",stdout);
int t; scanf("%d",&t);
for (int T=1;T<=t;T++)
{
scanf("%d%d",&n,&m);
memset(point,-1,sizeof(point));
memset(next,-1,sizeof(next));
memset(num,0,sizeof(num));
tot=-1;
cnt=1;
for (int i=1;i<=n;i++)
{
char s[M]; scanf("%s",s+1);
for (int j=1;j<=m;j++)
{
if (s[j]=='#') map[i][j]=1;
if (s[j]=='.') map[i][j]=-1;
if (s[j]=='?') map[i][j]=0,belong[i][j]=++cnt;
}
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (i%2) { if (j%2) vis[i][j]=1; }
else if (!(j%2)) vis[i][j]=1;
int ans=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (map[i][j]==1) ans+=(4-calc2(i,j));
int s=1; int t=n*m+2;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (!map[i][j])
{
ans+=4;
int t1=4;
int t2=2*calc2(i,j);
//cout<<i<<" "<<j<<" "<<t2<<endl;
if (vis[i][j]) add(s,belong[i][j],t1),add(belong[i][j],t,t2);
else add(s,belong[i][j],t2),add(belong[i][j],t,t1);
if (vis[i][j])
{
for (int k=0;k<4;k++)
{
int nowx=i+xx[k];
int nowy=j+yy[k];
if (nowx>0&&nowy>0&&nowx<=n&&nowy<=m&&!map[nowx][nowy])
add(belong[i][j],belong[nowx][nowy],2);//cout<<i<<" "<<j<<" "<<nowx<<" "<<nowy<<endl;
}
}
}
//cout<<ans<<endl;
printf("Case #%d: %d\n",T,ans-isap(s,t));
}
}