您的位置:首页 > 其它

Codeforces Zepto Code Rush 2014 -C - Dungeons and Candies

2014-06-14 14:16 507 查看
这题给的一个教训:Codeforces没有超时这个概念。本来以为1000*(1000+1)/2*10*10要超时的。结果我想多了。

这题由于k层都可能有关系,所以建一个图,每两个点之间连边,边权为n*m和他们之间的差值*w的最小值,然后求一个最小生成树就可以得出结果。且可以证明不会存在环。由于边比较稠密,用Prim算法求最小生成树。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define Mod 1000000007
using namespace std;
#define N 2007

char mp[1006][12][12];
int G[1006][1005],from[1006];
int n,m,res,id,k,w;
int vis[1005],len[1005];

struct Ans
{
int ind,pre;
}ans[1007];

int min(int ka,int kb)
{
if(ka < kb)
return ka;
return kb;
}

int dif(char a[12][12],char b[12][12])
{
int cnt = 0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(a[i][j] != b[i][j])
cnt++;
}
}
return cnt;
}

void Prim()
{
int i,j,tag,mini;
res = 0;
id = 0;
memset(vis,0,sizeof(vis));
memset(from,0,sizeof(from));
for(i=1;i<=k;i++)
len[i] = n*m;   //最大为n*m
for(i=1;i<=k;i++)
{
mini = Mod;
for(j=1;j<=k;j++)
{
if(!vis[j] && len[j] < mini)
{
mini = len[j];
tag = j;
}
}
if(mini == Mod)
return;
res += len[tag];
if(len[tag] == n*m)
ans[id].ind = tag,ans[id++].pre = 0;
else
ans[id].ind = tag,ans[id++].pre = from[tag];
vis[tag] = 1;
for(j=1;j<=k;j++)
{
if(!vis[j] && len[j] > G[tag][j])
{
len[j] = G[tag][j];
from[j] = tag;
}
}
}
}

int main()
{
int i,j;
while(scanf("%d%d%d%d",&n,&m,&k,&w)!=EOF)
{
id = 0;
for(i=1;i<=k;i++)
{
for(j=0;j<n;j++)
scanf("%s",mp[i][j]);
}
int T = n*m;
for(i=1;i<=k;i++)
{
for(j=i+1;j<=k;j++)
G[j][i] = G[i][j] = min(dif(mp[i],mp[j])*w,T);
G[i][i] = 0;
}
Prim();
printf("%d\n",res);
for(i=0;i<id;i++)
printf("%d %d\n",ans[i].ind,ans[i].pre);
}
return 0;
}


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