码迷,mamicode.com
首页 > 其他好文 > 详细

UVALive - 4097:Yungom(逼近 贪心)(DP)

时间:2019-06-07 13:10:11      阅读:102      评论:0      收藏:0      [点我收藏+]

标签:scan   前缀   turn   需要   路径   div   维护   uvalive   max   

pro:有D个字母,每个字母有自己的权值,现状需要用它们拼出N个单词,使得这些单词互相不为另外一个的前缀。 且单词的权值和最小。D<=200; N<=200;

sol:如果建立字典树,那个每个单词的权值权值救赎根到叶子的路径权重和。 感觉有点想哈夫曼树,但是没什么大的关系,因为不能倒推。

由于ND比较小,我们直接贪心,维护一个大小为N+D的数组b[],一直更新,原则如下:每次排序b[],把 b[1]替换为b[1]+a[];一直操作,直到不能再变小为止。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=410;
const ll inf=1LL<<45;
ll a[maxn],b[maxn];
int main()
{
    int N,D;ll ans;
    while(~scanf("%d%d",&N,&D)&&(N||D)){
        ans=0;
        rep(i,1,D) scanf("%lld",&a[i]);
        sort(a+1,a+D+1);
        rep(i,1,D) b[i]=a[i];
        rep(i,1,N)  b[i+D]=inf;
        rep(i,1,N) ans+=b[i];
        while(1){
            rep(i,1,D) b[i+N]=b[1]+a[i];
            b[1]=b[N+D];
            sort(b+1,b+N+D);
            ll sum=0;
            rep(i,1,N) sum+=b[i];
            if(sum<ans) ans=sum;
            else break;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

当然,也可以DP来做,dp[i][j]表示根有i个儿子,j个叶子时的最小代价。

 

UVALive - 4097:Yungom(逼近 贪心)(DP)

标签:scan   前缀   turn   需要   路径   div   维护   uvalive   max   

原文地址:https://www.cnblogs.com/hua-dong/p/10987800.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!