题解 P2753 【[USACO4.3]字母游戏Letter Game】

· · 题解

这一道题也没有什么算法了,就是纯靠思维来做的

在输入的字母之中,有很多个都是不行的(或超出范围的),

所以我们只用记录可以用的单词

找完可以用的单词,就用两重for循环找出最大值并且直接

记录,最后输出就可以了,把小写字母a,b,c,d变成1,2,3,4 就是

ss[]-'a'+1

代码如下:

#include<bits/stdc++.h>
using namespace std;
struct node
{
    int x,y;//记录最大值,x记录被选单词的序号,如果y是0,就只有x一个 
}result[5100];int len,maxx=0;
struct node1
{
    char s[11];
    int len,score;//记录单词 
}st[5100];int n;
char ss[31];
const int s[27]={0,2,5,4,4,1,6,5,5,1,7,6,3,5,2,3,5,7,2,1,2,4,6,6,7,5,7};//分值 
int flag[31];//flag记录每个字母最多可以出现多少次 
bool pd()//判断这一个是否可以 
{
    int i,k[31];memset(k,0,sizeof(k));
    for(i=1;i<=strlen(ss+1);i++)
    {
        k[ss[i]-'a'+1]++;
        if(k[ss[i]-'a'+1]>flag[ss[i]-'a'+1]) return false;//如果超出范围,就肯定不可以了 
    }
    return true;
}
bool check(int x,int y)//判断两个加起来是否超出范围 
{
    int i,k[31];memset(k,0,sizeof(k));
    for(i=1;i<=st[x].len;i++)
    {
        k[st[x].s[i]-'a'+1]++;
        if(k[st[x].s[i]-'a'+1]>flag[st[x].s[i]-'a'+1]) return false;
    }
    for(i=1;i<=st[y].len;i++)
    {
        k[st[y].s[i]-'a'+1]++;
        if(k[st[y].s[i]-'a'+1]>flag[st[y].s[i]-'a'+1]) return false;
    }
    return true;
}
int main()
{
    int i,j;
    scanf("%s",ss+1);
    for(i=1;i<=strlen(ss+1);i++) flag[ss[i]-'a'+1]++;//记录 
    while(scanf("%s",ss+1)!=EOF)
    {
        if(ss[1]=='.') break;//如果输入到句号,就推出 
        if(pd()==true)//如果这个单词没有超出范围 
        {
            n++;
            st[n].len=strlen(ss+1);
            for(i=1;i<=st[n].len;i++)//把这个单词记录下来 
            {
                st[n].s[i]=ss[i];
                st[n].score=st[n].score+s[ss[i]-'a'+1];//分值 
            }
        }
    }
    for(i=1;i<=n;i++)
    {
        if(st[i].score>maxx)//先找单独一个单词,如果超过分值 
        {
            len=1;//重置并且记录 
            result[1].x=i;
            maxx=st[i].score;
        }
        else if(st[i].score==maxx)//如果等于最大值 
        {
            len++;//增加一个 
            result[len].x=i;
        }
        for(j=i;j<=n;j++)//找后面的(包括自己,因为一个单词可以用两次) 
        {
            if(check(i,j)==true)//如果可以 
            {
                if(st[i].score+st[j].score>maxx)//更新最大值 
                {
                    len=1;result[1].x=i;result[1].y=j;
                    maxx=st[i].score+st[j].score;
                }
                else if(st[i].score+st[j].score==maxx)
                {
                    len++;result[len].x=i;result[len].y=j;
                }
            }
        }
    }
    printf("%d\n",maxx);//直接输出,因为已经按照字典序排好了,没有必要再排一次 
    for(i=1;i<=len;i++)//输出 
    {
        for(j=1;j<=st[result[i].x].len;j++) printf("%c",st[result[i].x].s[j]);
        if(result[i].y>0)
        {
            printf(" ");
            for(j=1;j<=st[result[i].y].len;j++) printf("%c",st[result[i].y].s[j]);
        }
        printf("\n");
    }
    return 0;
}