usaco 4.3 Letter Game(枚举+字符串hash)

Letter Game
IOI 1995
 
Figure 1: Each of the 26 lowercase letters and its value

Letter games are popular at home and on television. In one version of the game, every letter has a value, and you collect letters to form one or more words giving the highest possible score. Unless you have `a way with words', you will try all the words you know, sometimes looking up the spelling, and then compute the scores. Obviously, this can be done more accurately by computer.

Given the values in Figure 1, a list of words, and the letters collected: find the highest scoring words or pairs of words that can be formed.

PROGRAM NAME: lgame

INPUT FORMAT

One line with a string of lowercase letters (from ` a ' to ` z '). The string consists of at least 3 and at most 7 letters in arbitrary order.

SAMPLE INPUT (file lgame.in)

prmgroa

DICTIONARY FORMAT

At most 40,000 lines, each containing a string of at least 3 and at most 7 lowercase letters. At the end of this file is a line with a single period (` . '). The file is sorted alphabetically and contains no duplicates.

SAMPLE DICTIONARY (file lgame.dict)

profile
program
prom
rag
ram
rom
.

OUTPUT FORMAT

On the first line, your program should write the highest possible score, and on each of the following lines, all the words and/or word pairs from file lgame.dict with this score. Sort the output alphabetically by first word, and if tied, by second word. A letter must not occur more often in an output line than in the input line. Use the letter values given in Figure 1.

When a combination of two words can be formed with the given letters, the words should be printed on the same line separated by a space. The two words should be in alphabetical order; for example, do not write `rag prom', only write `prom rag'. A pair in an output line may consist of two identical words.

SAMPLE OUTPUT (file lgame.out)

This output uses the tiny dictionary above, not the lgame.dict dictionary.

24
program
prom rag

题意:给你一个字符串,你可以用里面的字母来拼出单词,使得单词的总值最大,不用全部用完,单词最多两个

分析:首先将字典里的单词就算好值,装进hash标里面,方便查询,接着枚举字母构成单词,查找构成的单词的值,与最大值判断,并记录即可。。。

代码:

/*
ID: 15114582
PROG: lgame
LANG: C++
*/
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int mm=500007;
const int mn=44444;
int w[]={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};
struct hashTable
{
    int h[mm],p[mn],v[mn],size;
    char s[mm][9];
    int hash(char *a)
    {
        int h=0;
        while(*a)h=h*131+(*a++);
        return (h&0x7FFFFFFF)%mm;
    }
    void insert(char *a,int val)
    {
        int i,id=hash(a);
        for(i=h[id];i>=0;i=p[i])
            if(!strcmp(s[i],a))return;
        strcpy(s[size],a);
        v[size]=val,p[size]=h[id],h[id]=size++;
    }
    int find(char *a)
    {
        int i,id=hash(a);
        for(i=h[id];i>=0;i=p[i])
            if(!strcmp(s[i],a))return i;
        return -1;
    }
    void clear()
    {
        size=0;
        memset(h,-1,sizeof(h));
    }
}g;
char word[9],neword[9],tmp1[9],tmp2[9];
int vis[9]={0},out[mn][2],ans,r,n;
void count()
{
    for(int i=0,j,a,b;i<n;++i)
    {
        tmp1[i]=neword[i];
        tmp1[i+1]='\0';
        a=g.find(tmp1);
        if(a>-1)
        {
            if(g.v[a]>ans)
            {
                ans=g.v[a];
                out[0][0]=a;
                out[0][1]=-1;
                r=1;
            }
            else if(g.v[a]==ans)
            {
                out[r][0]=a;
                out[r][1]=-1;
                ++r;
            }
            for(j=i+1;j<n;++j)
            {
                tmp2[j-i-1]=neword[j];
                tmp2[j-i]='\0';
                b=g.find(tmp2);
                if(b>-1)
                {
                    if(strcmp(g.s[a],g.s[b])>0)swap(a,b);
                    if(g.v[a]+g.v[b]>ans)
                    {
                        ans=g.v[a]+g.v[b];
                        out[0][0]=a;
                        out[0][1]=b;
                        r=1;
                    }
                    else if(g.v[a]+g.v[b]==ans)
                    {
                        out[r][0]=a;
                        out[r][1]=b;
                        ++r;
                    }
                }
            }
        }
    }
}
void dfs(int j)
{
    if(j>=n)
    {
        count();
        return;
    }
    for(int i=0;i<n;++i)
        if(!vis[i])
        {
            neword[j]=word[i];
            vis[i]=1;
            dfs(j+1);
            vis[i]=0;
        }
}
int main()
{
    int i,j,val;
    freopen("lgame.dict","r",stdin);
    g.clear();
    while(scanf("%s",word),word[0]!='.')
    {
        for(val=i=0;i<strlen(word);++i)
            val+=w[word[i]-'a'];
        g.insert(word,val);
    }
    freopen("lgame.in","r",stdin);
    freopen("lgame.out","w",stdout);
    while(~scanf("%s",word))
    {
        ans=0;
        n=strlen(word);
        dfs(0);
        printf("%d\n",ans);
        for(i=0;i<r;++i)
            for(j=i+1;j<r;++j)
                if(strcmp(g.s[out[i][0]],g.s[out[j][0]])>0||
                 (strcmp(g.s[out[i][0]],g.s[out[j][0]])==0
                  &&strcmp(g.s[out[i][1]],g.s[out[j][1]])>0))
                {
                    swap(out[i][0],out[j][0]);
                    swap(out[i][1],out[j][1]);
                }
        for(j=i=0;i<r;++i)
            if(strcmp(g.s[out[i][0]],g.s[out[j][0]])!=0
                  ||strcmp(g.s[out[i][1]],g.s[out[j][1]])!=0)
            {
                ++j;
                out[j][0]=out[i][0];
                out[j][1]=out[i][1];
            }
        r=j+1;
        for(i=0;i<r;++i)
        {
            printf("%s",g.s[out[i][0]]);
            if(out[i][1]>-1)printf(" %s",g.s[out[i][1]]);
            puts("");
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是P4087 [USACO17DEC]Milk Measurement的c++代码: ```c++ #include<bits/stdc++.h> using namespace std; int n,d,i,x,minn=1e9,maxn=-1e9,sum=7;//注意sum要初始化为7,因为一开始有三个人挤奶! map<int,int> mp; struct node{ int day,milk,id;//day表示某一天,milk表示这一天的产奶量,id表示这头牛的编号 }a[100010]; bool cmp(node x,node y){ return x.day<y.day; } int main(){ scanf("%d%d",&n,&d); for(i=1;i<=n;i++){ scanf("%d%d%d",&a[i].day,&a[i].id,&a[i].milk); minn=min(minn,a[i].id);//记录最小的牛的编号 maxn=max(maxn,a[i].id);//记录最大的牛的编号 } sort(a+1,a+n+1,cmp);//排序 for(i=1;i<=n;i++){ int p=a[i].id; mp[p]+=a[i].milk;//记录每头牛产奶总量 if(mp[p]-a[i].milk>=mp[minn]&&mp[p]>=mp[minn]){//如果这头牛的产奶总量减去这一天的产奶量后等于最小产奶量且这头牛的产奶总量大于等于最小产奶量 sum--; } if(mp[p]>=mp[maxn]&&mp[p]-a[i].milk<mp[maxn]){//如果这头牛的产奶总量大于等于最大产奶量且这头牛的产奶总量减去这一天的产奶量小于最大产奶量 sum++; } if(mp[p]-a[i].milk<mp[maxn]&&mp[p]>=mp[maxn]){//如果这头牛的产奶总量减去这一天的产奶量小于最大产奶量且这头牛的产奶总量大于等于最大产奶量 if(mp[maxn]-mp[p]+a[i].milk>0)sum++; } mp[p]-=a[i].milk;//减去这一天的产奶量 if(i==n||a[i].day!=a[i+1].day){//如果到了新的一天或者到了最后一天 if(mp[maxn]!=mp[a[i].id]&&mp[a[i].id]>=mp[maxn])sum++;//如果这头牛的产奶总量不等于最大产奶量且这头牛的产奶总量大于等于最大产奶量 if(mp[maxn]==mp[a[i].id]){//如果这头牛的产奶总量等于最大产奶量 if(a[i].id==maxn)sum+=0;//如果这头牛就是最大产奶量的牛,那么不需要增加计数器 else sum++;//否则需要增加计数器 } if(mp[minn]!=mp[a[i].id]&&mp[a[i].id]>=mp[minn])sum++;//如果这头牛的产奶总量不等于最小产奶量且这头牛的产奶总量大于等于最小产奶量 if(mp[minn]==mp[a[i].id]){ if(a[i].id==minn)sum+=0;//如果这头牛就是最小产奶量的牛,那么不需要增加计数器 else sum++;//否则需要增加计数器 } } } printf("%d\n",sum); return 0; } ``` 该题的解题思路是模拟,需要注意细节问题。我们可以首先将输入的数据按天数排序,然后模拟每一天挤奶的情况,并根据题目要求进行计数即可。具体细节请见代码注释。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值