cf557c

题目大意:

有一张桌子,有n个腿。第i根腿的长度是li。

现在要拿掉一些腿,使得桌子稳定,拿掉第i根腿需要di的能量。

稳定的条件是,假如拿掉若干条腿之后,桌子还有k个腿,那么长度最长的腿的数目要超过一半。比如桌子有5根腿,那么至少要有三根腿是最长的。另外,只有一根腿的桌子是稳定的,两个腿的桌子想要稳定,必需长度是一样的。

你的任务是拿掉若干腿,使得桌子稳定,并且所消耗的能量要最少。


思路:按长度排序,枚举每个长度,比枚举长度长的全拆掉,前面的拆掉 枚举长度数量-1


#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <iomanip>

using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define maxn 100005
#define MOD 1000000007
#define mem(a , b) memset(a , b , sizeof(a))
#define LL long long
#define INF 100000000
int n;
int all = 0;
int cnt[205];
struct node
{
    int l , val;
}a[maxn] , tmp[maxn];

bool cmp(node n1 , node n2)
{
    if(n1.l == n2.l) return n1.val < n2.val;
    return n1.l < n2.l;
}

bool cmp2(node n1 , node n2)
{
    return n1.val < n2.val;
}

void solve()
{
    int ans = INF;
    int i = 0 , cost = 0 , num = 0 , j;
    while(i < n)
    {
        cost = a[i].val;
       // cnt[a[i].val]++;
        num = 1;
        for(j = i + 1; j < n ; j ++)
        {
            if(a[j].l == a[j-1].l) num++,cost+= a[j].val  ;
            else break;
        }
        all-=cost;
        cost = all;
      /*  memcpy(tmp , a , (j-num)*8);
        sort(tmp , tmp+j-num , cmp2);
        int up = j + 1 - num - num;
        for(int k = 0 ; k < up;k ++) cost += tmp[k].val;*/
            int tmp = num;
            num =  j + 1 - num - num;
            //num++;
            for(int k = 1 ; k <= 200 ; k ++)
            {
                if(cnt[k])
                {
                  //  cout << k << endl;
                    if(cnt[k] < num) cost += k * cnt[k] , num -= cnt[k];
                    else {cost += k * num;break;}
                }
            }
        ans = min(ans , cost);
      //  cout << ans <<  " test" << endl;
        for(int k = i ; k < j ; k++)
        {
            cnt[a[k].val]++;
        }
        i = j;
    }
    printf("%d\n" , ans);
}

int main()
{
    while(scanf("%d" , &n) != EOF )
    {
        all = 0;
        mem(cnt , 0);
        for(int i = 0 ; i < n ;i ++)
            scanf("%d" , &a[i].l);
        for(int i = 0 ; i < n ; i ++)
            scanf("%d" , &a[i].val) ,all += a[i].val;

        sort(a , a + n , cmp);
        solve();
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值