Solution to a problem --gift (dfs order processing tree knapsack problem)

Solution to a problem --gift (dfs order processing tree knapsack problem)

This question ssw02 reference to God Chiang code
still two campuses rank1 case simulation game, Jiang God T1 hung up

Welcome to reprint ssw02's blog: https://www.cnblogs.com/ssw02/p/11640828.html

topic

Questions face Description: A tree knapsack problem with a restriction

Input: A tree various constraints + (attribute)

The maximum value and the ratio of consumption: Output

Thinking

Before solving the problem, this question first off say [JSOI2016] Best Group

First binary answer (fractional programming routine 01), then the process as val [i] = (Value - mid × spent)

A bit different transfer equation DP. Thanks to staffing limitations at least one and a [i], we might consider, dp [i] j value [j] is no longer chose j kinds of items, but there are individual j has received items.

Then consider the issue of transfer, we consider this situation: Everyone has a gift, and now in the hands of some gifts. We obviously want to optimum value, certainly the remaining surplus items and then distributed to the existing articles of people, so that you can get the rest of the val> contributions 0 items.
sodp[ 一个状态 ][ M ] = dp[ 前一个状态 ][ M ]

At the same time we take into account only at least a staff, is a legitimate answer, in order to try to reach a staff of restrictions fast, we will certainly give priority to this article points to an item in the sub-items do not get people, which would allow us to have more full after the election of a more superior choice items above.

Simple example: If you can not fill to fill, however, for example, there is no personal items 5, but this time you have two val 5, -10, number 34 for the item, you can not avoid in any case val selected from negative to articles, and the case is filled can be freely selected. (Ssw02 only Hu mouth, emotional correctness analysis)

Then there is timely dependency tree knapsack problem.

We can consider the usual practice to use a tree backpack dp [i] [j] process i j subtree individuals have a gift.

Dfs sequence may be used to convert the sequence to attribute dependencies. Using not selected subtree jump operation .dp [i] [j] represents a post dfs sequence i j individuals present case.

Code

Chiang God ssw02 reference code selects the smaller constant sequence DP dfs written, this approach flashback enumeration and the enumeration sequence is no essential difference

#include<bits/stdc++.h>
using namespace std ;
#define ll long long
const int MAXN = 1005 ;
inline int read(){
    int s=0 ; char g=getchar() ; while(g>'9'||g<'0')g=getchar() ;
    while(g>='0'&&g<='9')s=s*10+g-'0',g=getchar() ; return s ;
}
int N , K ; 
double p[ MAXN ] , s[ MAXN ] , val[ MAXN ] , dp[ MAXN ][ MAXN ];
int  tot = 1 , spread[ MAXN ], head[ MAXN ] , to[ MAXN*2 ] , nex[ MAXN*2 ] ;
int  cnt = 0 , dfn[ MAXN ] , id[ MAXN ], size[ MAXN ] ;
void  add( int x , int y ){
    to[ ++tot ] = y , nex[ tot ] = head[ x ] , head[ x ] = tot ;
}
inline void  dfs( int u , int fa ){//从0开始只是因为树根为 0 , 刨除贡献 
    dfn[ u ] = cnt , id[ cnt++ ] = u , size[ u ] = 1 ;
    for( int i = head[ u ] ; i ; i = nex[ i ] ){
        dfs( to[ i ] , u  ) ;
        size[ u ] += size[ to[ i ] ] ;
    }
    return ;
} 
inline bool check( double x ){
    for( int i = 1 ; i <= N ; ++i )val[ i ] = p[ i ] - x*s[ i ] ;
    dp[ N+1 ][ 0 ] = 0 ;
    for( int i = 1; i <= K ; ++i ) dp[ N+1 ][ i ] = -1e9 ;
    for( int i = N ; i > 0 ; --i ){
        int u = id[ i ];
        for( int j = 0 ; j <= K ; ++j ){
            dp[ i ][ j ] = dp[ i+size[ u ] ][ j ] ;
            if(j <= spread[u] ){
                if(dp[i+1][0]+val[u]>dp[i][j])
                {
                    dp[i][j]=dp[i+1][0]+val[u];
                }
            }
            else
            {
                if(dp[i+1][j-spread[u]]+val[u]>dp[i][j])
                {
                    dp[i][j]=dp[i+1][j-spread[u]]+val[u];
                }
            }
        }
    }
    return dp[ 1 ][ K ] >= 0 ;
}
/*错误代码
for( int i = 1 ; i <= N ; ++i )val[ i ] = p[ id[i] ] - x*s[ id[i] ] ;
    dp[ 0 ][ 0 ] = 0 ; 
    for( int j = 0 ; j <= K ; ++j )dp[ 0 ][ j ] = -1e8 ; 
    for( int i = 0 ; i <= N ; ++i )
       for( int j = 0 ; j <= min( i , K ) ; ++j ){
           if( j <= spread[ id[ i ] ] )
              dp[ i+1 ][ j+1 ] = max( dp[ i+1 ][ j+1 ] , dp[ i ][ 0 ]+val[ i ] ) ;
           else
              dp[ i+1 ][ j+1 ] = max( dp[ i+1 ][ j+1 ] , dp[ i+1 ][ j-spread[ id[i] ]] + val[ i ] ) ;
           dp[ i+size[ id[i] ] ][ j ] = max( dp[ i+size[ id[i] ] ][ j ] , dp[ i ][ j ] ) ;
       }
    return dp[ N+1 ][ K ] >= 0 ;
*/
void  dx( double l , double r ){
    while( r - l > 0.0000001 ){
        double mid = ( l+r )/2.0 ;
        if( check(mid) )l = mid ; else r = mid ; 
    }
    printf("%0.10lf",l) ;
}
int main(){ 
    //freopen("gift.in","r",stdin);
    //freopen("gift.out","w",stdout);
    N = read() , K = read() ; int m1 , m2 , m3 ; double ma = -1.0 ;
    for( register int i = 1 ; i <= N ; ++i ){
        spread[ i ] = read() , p[ i ] = 1.0*read() , s[ i ] = 1.0*read() , m3 = read() ; 
        add( m3 , i ) ; 
    }
    dfs( 0 , 0 ) ;
    val[ 0 ] = 0.0 ;
    dx( (double)0 , 100000 ) ; 
    return 0 ;
}

If insufficient, please point out.

Guess you like

Origin www.cnblogs.com/ssw02/p/11640828.html