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

zoj 3305 - Get Sauce

时间:2014-12-30 20:47:38      阅读:308      评论:0      收藏:0      [点我收藏+]

标签:

题目:打酱油(⊙v⊙),有n种原料,和一些配方,现在要在每种原料最多用一次的情况下,配出最多的配方。

分析:dp,01背包。因为原料种类少,可以用2进制表示每种配方,按配方01背包即可,(容积(1<<n)-1)。

            这里在计算过程中需要剪枝,否则会TLE,配方有包含关系取下的即可。(Orz大黄。。)

说明:本来觉得搜索状态会快一点,结果剪枝后还 1120ms。。。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int  Sauce[ 50001 ][ 16 ];
int  Count[ 50001 ];
int  Value[ 50001 ];
bool U[ 50001 ];
int  F[ 1<<16 ];

int value( int id )
{
    int sum = 0;
    for ( int i = 0 ; i < Count[ id ] ; ++ i )
        sum += (1<<(Sauce[ id ][ i ]-1));
    return sum;
}

int cmp( const void* a, const void* b )
{
    return *((int *)b) - *((int *)a);
}

int main()
{
    int n,m;
    while ( scanf("%d%d",&m,&n) != EOF ) {
        for ( int i = 1 ; i <= n ; ++ i ) {
            scanf("%d",&Count[ i ]);
            for ( int j = 0 ; j < Count[ i ] ; ++ j )
                scanf("%d",&Sauce[ i ][ j ]);
        }
        
        memset( F, 0, sizeof( F ) );
        memset( U, 0, sizeof( U ) );
        for ( int i = 1 ; i <= n ; ++ i )
            Value[ i ] = value( i );
    
        qsort( &Value[ 1 ], n , sizeof( int ), cmp );
        for ( int i = 1 ; i <= n ; ++ i )
        for ( int j = i+1 ; j <= n ; ++ j )
            if ( (Value[ i ]&Value[ j ]) == Value[ j ] ) {
                U[ i ] = 1;
                break;
            }
        
        int  M = (1<<m)-1;
        for ( int i = 1 ; i <= n ; ++ i ) {
            if ( U[ i ] ) continue;
            for ( int j = M ; j >= 0 ; -- j )
                if ( (j&Value[ i ]) == Value[ i ] && F[ j ] <= F[ j-Value[ i ] ] ) 
                    F[ j ] = F[ j-Value[ i ] ] + 1;
        }
        
        printf("%d\n",F[ M ]);
    }
    return 0;    
}

zoj 3305 - Get Sauce

标签:

原文地址:http://blog.csdn.net/mobius_strip/article/details/42270443

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