题意:
给你一堆车牌号,除了一个原始的,其它的车牌号都是从某个车牌号中派生出来的(改变一些字母)。以两个车牌号不同的字母数为代价,问你算出所有车牌号最小的代价是多少。
题解:
这道题的题意我看了半天最后才弄懂。只要把每个车牌号都当成一个点就去计算每个点之间的不同数然后用最小生成树去计算就可以算出结果了。稠密图最好用prim,这里我有个疑问就是。。。。2000*7*2000*7再来个2000*(2000+2000)这时间复杂度不爆炸吗?为什么我用朴素的prim能过呢。。。这数据也太水了吧。。。
题外话:
这之后我去试了一下堆优化,发现超内存了。。。。难道是我写的不对吗?有大佬去试试吗
//朴素的prim
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
const int MAXN=2005;
int dis[MAXN];
bool vis[MAXN];
int map[MAXN][MAXN];
char s[MAXN][8];
int n;
void prim()
{
int sum=0;
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++)
dis[i]=map[1][i];
vis[1]=true;
for(int i=1;i<=n;i++)
{
int MIN=INF,k=0;
for(int j=1;j<=n;j++)
if(!vis[j]&&MIN>dis[j])
MIN=dis[j],k=j;
vis[k]=true;
for(int j=1;j<=n;j++)
if(!vis[j]&&map[k][j]<dis[j])
dis[j]=map[k][j];
}
for(int i=1;i<=n;i++) sum+=dis[i];
printf("The highest possible quality is 1/%d.\n",sum);
}
int main()
{
while(~scanf("%d",&n),n)
{
memset(map,INF,sizeof(map));
for(int i=1;i<=n;i++)
map[i][i]=0;
for(int i=1;i<=n;i++)
scanf("%s",&s[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i==j)
continue;
int k=0;
for(int ii=0;ii<7;ii++)
{
if(s[i][ii]!=s[j][ii])
k++;
}
if(map[i][j]>k)
map[i][j]=map[j][i]=k;
}
prim();
}
}
//这样虽然过了(玄学啊,因为我估算时间复杂度的时候还想着怎么优化),但是在极限2000个字符串的情况下,肯定爆炸,是时候要学一下堆优化了。