uva 1010

uva 1010

【Sol】 DP+最短路

经试验,原先的n个串应该没有相同的

引用《算法艺术与信息学竞赛》P148

#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<iostream>
#include<queue>
using namespace std;
#define N 22
#define M 500
const int inf=0x3f3f3f3f;
char word[N][N];
bool vis[N][N];
struct node{
    int p;
    string s;
}d[N][N];
queue<int > Q1,Q2;
int n,len[N];
const char* printans;
//返回 0 无关系
//返回1 S1是S2的前缀 ( L1<L2)
//返回2 S2是S1的前缀 ( L1>L2)
//返回3 相等 ( L1=L2)
//返回>=2      L1>=L2
int isprefix(char *s1, char *s2)
{   int l1=strlen(s1), l2=strlen(s2);
    for (int i=0;i<l1&&i<l2;i++)
        if (s1[i]!=s2[i])return 0;
    if (l1==l2) return 3;
    if (l1<l2)  return 1;
    if (l1>l2)  return 2;
}

void Qclear()
{
    while (!Q1.empty()) Q1.pop();
    while (!Q2.empty()) Q2.pop();
}

bool minize(int a,int b,int p,string s)
{
         if (p<d[a][b].p) {d[a][b].p=p; d[a][b].s=s; return 1;}
    else if (p==d[a][b].p&&s<d[a][b].s){d[a][b].s=s; return 1;}
    return 0;
}
void spfa()
{   Qclear();
    memset(vis,0,sizeof(vis));
    for (int i=1;i<=n;i++)
    for (int j=1;j<=len[i];j++)
         if (d[i][j].p!=inf)
             {  Q1.push(i); Q2.push(j);
                vis[i][j]=1;
             }
    while (!Q1.empty())
         {
             int nowa=Q1.front(),nowb=Q2.front();
             int p=d[nowa][nowb].p;
             string s=d[nowa][nowb].s;
             Q1.pop(); Q2.pop();
             for (int i=1;i<=n;i++)
                {if (isprefix(word[nowa]+nowb,word[i])>=2)
                    if (minize(nowa,nowb+len[i],p+len[i],s+string(word[i])))
                         {Q1.push(nowa); Q2.push(nowb+len[i]);}
                 if (isprefix(word[i],word[nowa]+nowb)>=2)
                    if (minize(i,len[nowa]-nowb,p+len[nowa]-nowb,s+string(word[nowa]+nowb)))
                         {Q1.push(i); Q2.push(len[nowa]-nowb);}
                }
         }

}
void doit()
{
    for (int i=1;i<=n;i++)
        {scanf("%s",word[i]);
         len[i]=strlen(word[i]);
        }
    for (int i=1;i<=n;i++)
    for (int j=1;j<=len[i];j++)
        d[i][j].p=inf;
    for (int i=1;i<=n;i++)
    for (int j=1;j<=n;j++)
    if (i!=j)
        if (isprefix(word[j],word[i])>=2)
            {   d[j][len[i]].p=len[i];
                d[j][len[i]].s=string(word[i]);
            }
    int ans=inf;
    string anss="";
    spfa();
    for (int i=1;i<=n;i++)
        if (ans>d[i][len[i]].p)
            {ans=d[i][len[i]].p; anss=d[i][len[i]].s;}
        else if (ans==d[i][len[i]].p&&anss>d[i][len[i]].s)
             anss=d[i][len[i]].s;
    printf("%d bits\n%",ans);

    const char* printans=anss.c_str();
    int hhh=(ans-1)/20;
    for (int i=0;i<hhh;i++)
     {  for (int j=0;j<20;j++)
            printf("%c",*(printans+i*20+j));
        printf("\n");
     }
    for (int j=0;j<ans-hhh*20;j++)
            printf("%c",*(printans+j+hhh*20));
    printf("\n");

}
int main()
{   int i=0;
    while (scanf("%d",&n),n)
        {printf("Code %d: ",++i);
         doit();
         printf("\n");
        }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值