题目:你要去自己买个组装机,现在给你每个零件的类别、名字、价钱、级别,以及你有的钱数,
求能组装成的机器的最大级别(机器的所有零件中的最小级别,即最小值最大)。
分析:分治、dp。看起来很像是dp,不过本题可以利用二分求解(我这里二分套二分了)。
首先,将所有的零件按照级别递减排序,此时装机的总代价递减(比原来多了新的参考零件);
然后,二分级别,每次找到不低于当前级别的所有零件(排序后,一定连续,可以二分求解);
计算这些零件能够构成计算机的最小代价,不能组成就返回max;
最后,求出的结果,即为可以得到的最大的级别。
说明:题意略坑,要求每种市面上有的零件都要买一件,RE好多次╮(╯▽╰)╭。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
using namespace std;
typedef struct cnode
{
char type[21];
char name[21];
int price;
int level;
}component;
component C[1004];
char list[1004][21];
int gettype( char* type, int n )
{
for ( int i = 0 ; i < n ; ++ i )
if ( !strcmp( list[i], type ) )
return i;
strcpy(list[n], type);
return n+1;
}
bool cmp( component a, component b )
{
return a.level > b.level;
}
int temp[1004];
int test( int n, int s )
{
int mark = 0,sum = 0,t;
for ( int i = 0 ; i < s ; ++ i )
temp[i] = 1000001;
for ( int i = 0 ; i < n ; ++ i ) {
t = gettype( C[i].type, s );
if ( temp[t] > C[i].price )
temp[t] = C[i].price;
}
for ( int i = 0 ; i < s ; ++ i )
if ( temp[i] == 1000001 )
return 1000000001;
else sum += temp[i];
return sum;
}
int bs( int r, int key )
{
int l = 0,mid;
while ( l < r ) {
mid = (r+l)/2;
if ( C[mid].level >= key )
l = mid+1;
else r = mid;
}
return r;
}
int main()
{
int n,m,p;
while ( ~scanf("%d",&n) )
while ( n -- ) {
scanf("%d%d",&m,&p);
int list_size = 0;
for ( int i = 0 ; i < m ; ++ i ) {
scanf("%s%s%d%d",&C[i].type,&C[i].name,&C[i].price,&C[i].level);
list_size = max(list_size, gettype( C[i].type, list_size ));
}
sort( C, C+m, cmp );
int mid,l = 0,r = m-1;
while ( l < r ) {
mid = (l+r)/2;
if ( test(bs(m-1,C[mid].level),list_size) > p )
l = mid+1;
else r = mid;
}
printf("%d\n",C[r].level);
}
return 0;
}
UVa 12124 - Assemble,布布扣,bubuko.com
原文:http://blog.csdn.net/mobius_strip/article/details/38376693