【2012中山市选】捡金子(gold)

15 篇文章 0 订阅
10 篇文章 0 订阅

Description

从前有一个迷宫,迷宫的外形就像一棵带根树,每个结点(除了叶子结点外)恰好有K个儿子。

一开始你在根结点,根结点的K个儿子分别标记为‘A’, ‘B’, ‘C’….,而结点‘A’的K个儿子结点分别标记为‘AA’,‘AB’,‘AC’……,依此类推。这棵树一共有L层。

现在你事先知道M个结点中有金子,并且你可以派出N个机器人去收集金子。首先你可以分别指定每一个机器人的目标结点,于是这些机器人就会收集从根结点到其目标结点这条路径上(包括目标结点)所有的金子,但是每个位置的金子只能被收集一次。

现在你需要制定一个目标的分配方案,使得收集到的金子最多。

Input

输入的第一行有4个整数:M,K,L,N。对应题目描述中的参数。

接下来M行,每行是一个字符串,表示所对应的结点上有金子。

Output

输出利用N个机器人所能捡到时最多几个结点上的金子。

Sample Input

样例1:
5 3 3 1
ACC
ACB
AB
AC
A

样例2:
5 3 3 2
ACC
ACB
AB
AC
A

Sample Output

样例输出1:
3

样例输出2:
4

Data Constraint

Hint

对于20%的数据有1<=M<=20.

对于40%的数据有1<=M<=2000.

对100%的数据,有1<=M<=50000,1<=K<=26,1<=L<=50,1<=N<=50

思路
设 f [x] [j] 表示以x为根节点,用j个机器人的最大拾金数
f[x][j]=max(f[x][j],f[x][j-k]+f[y][k]);

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char s[51],s1[1200010];
int last[1200010],t[1200010],next[1200010],a[1200010],len,tot,x,i,m,l,k,q,j,f[1200010][51],tot1;
bool b;
void insert(int x,int y)
{

    t[++tot1]=y,next[tot]=last[x],last[x]=tot;

}
void dfs(int x)
{

    int i,y,j,k;
    f[x][0]=0;
    for (i=last[x];i;i=next[i])
    {

            dfs(y=t[i]);
            for (j=q;j>-1;j--)
            {

                for (k=0;k<=j;k++)
                {
                    f[x][j]=max(f[x][j],f[x][j-k]+f[y][k]);

                }

            }

    }
    for (i=1;i<=q;i++)
        f[x][i]=f[x][i]+a[x];

}
int main()
{

    scanf("%d%d%d%d\n",&m,&k,&l,&q);
    for (i=1;i<=m;i++)
    {

        scanf("%s\n",s+1);
        len=strlen(s+1);
        x=0;
        for (j=1;j<=len;j++)
        {

            b=false;
            for (k=last[x];k;k=next[k])
            {

                if (s1[t[k]]==s[j])
                {

                    b=true,x=t[k];break;

                }

            }
            if (!b)
            {

                insert(x,++tot);
                x=tot,s1[x]=s[j];

            }

        }       
        a[x]=1;

    }
    dfs(0);
    printf("%d",f[0][q]);

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值