zoukankan      html  css  js  c++  java
  • Jzoj4210 我才不是萝莉控呢

    小Y:“小R你是萝莉控吗。”小R:“...” 
    为了避免这个尴尬的话题,小R决定给小Y做一道题。
    有一个长度为n的正整数数组A,满足艾> =艾+ 1,现在构造一个数组B,令的Bi = ΣA[j] (j∈[i,n])
    现在,有一个N * N的网格图,左下角坐标是(1,1),右上角坐标是(N,N)。有一个小SB正在坐标为(n,1)的位置,每一时刻,如果他现在在(x,y),他可以选择走到(x?-1,y + 1)或者(x, + 1)div 2),如果选择后者,他要支付Bx的代价。

    现在他想走到(1,1),你可以告诉他他支付的代价最少是多少吗?注意在任何时候他都不能离开这个网格图。

    因为我不是萝莉控所以这道题我开始并没有做出来

    好的先来做50分做法,我们搞一个dp,f[i][j]表示走到i,j的代价

    随便搞一下转移:f[i][j]->f[i-1][j+1],f[i][j]+b[i]->f[i][(j+1)/2]

    好的接下来讲一些不太相关的东西:

    哈夫曼树

    这种东西相信大家都应该知道怎么快速构建,一个堆就好了

    but这个东西有一种非常鬼畜的解法

    我们还是用dp,先将所有的数字从大到小排序

    令f[i][j]表示当前的树已经选入了i个数,还有j个空位的状态

    那么我们考虑两种转移

    1.在空位插入第i+1个数,那么代价就是d*a[i+1]

    2.将所有的空位建立2子节点(因为要符合哈夫曼树的性质),代价为0

    发现这样需要多一个状态d,非常不好,我们将转移改成以下形式


    1.在空位插入第i+1个数,代价为0

    2.将所有的空位建立2子节点(因为要符合哈夫曼树的性质),代价为Σa[i+1..n]

    容易发现二者等价

    写成方程式看看?

    f[i][j]->f[i+1][j-1]

    f[i][j]->f[i][j*2]+Σa[i+1..n]

    发现和上面那个问题的形式是一样的

    做完了,两者等价,所以答案就是A的哈夫曼树树根权值

    #include<queue>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    int T,n; long long ans=0; 
    priority_queue<int,vector<int>,greater<int> > q;
    int _18520(){
    	scanf("%d",&n); ans=0;
    	for(int x,i=1;i<=n;++i){
    		scanf("%d",&x);
    		q.push(x);
    	}
    	for(int x,i=n;i>1;--i){
    		x=q.top(); q.pop();
    		x+=q.top(); q.pop();
    		q.push(x); ans+=x; 
    	}
    	printf("%lld
    ",ans); q.pop();
    }
    int main(){
    	for(scanf("%d",&T);T--;_18520());
    }
  • 相关阅读:
    聊一聊Flutter的setState()
    Flutter + Android 混合开发
    Flutter防止布局溢出
    Flutter获取远程数据 刷新UI界面
    Flutter日常笔记
    POJ 3299 Humidex
    POJ 1207 The 3n + 1 problem
    POJ 1005 I Think I Need a Houseboat
    POJ 1004 Financial Management
    POJ1012
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/8449249.html
Copyright © 2011-2022 走看看