题意:题目给出的桌子的n条长度不一的腿,以及打断每条腿所需的花费。要求在最小的花费下,使桌子达到平衡。平衡的条件是最大腿的个数要大于总的腿数的一半。
思路:这道题刚开始往dp上考虑,结果怎么搞,都找不出最有子结构,导致状态无法定义,最后放弃dp。想着试一试枚举平衡时最大腿的长度,然后各种数组记录。本来以为会TLE,最后过了46ms。具体实现见代码。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAX = 100010;
const int INF = 1000000000;
struct Node{
int l, d;
bool operator < (const Node& rhs) const { //将桌子腿根据花费降序排列
return d > rhs.d;
}
}p[MAX];
int cnt[MAX], a[MAX], st[MAX];
/*
cnt[i]表示长度为i的桌子腿的数量
a[]降序存放桌子退的长度
st[i]表示长度为i的桌子腿全部打断所需要的花费
*/
int main(){
int n;
while (scanf("%d",&n) != EOF){
memset(cnt, 0, sizeof(cnt));
memset(st, 0, sizeof(st));
for (int i = 0; i<n; i++){
scanf("%d",&p[i].l);
cnt[p[i].l]++;
}
int s = 0;
for (int i = 0; i<n; i++){
scanf("%d", &p[i].d);
s += p[i].d;
st[p[i].l] += p[i].d;
}
sort(p, p+n);
int c = 0;
for (int i= MAX; i>0; i--) if (cnt[i] != 0){
a[c++] = i;
}
int ans = INF;
for (int i = 0; i<c; i++){ //枚举稳态是最大的桌子腿长度
int res = st[a[i]]; //res贪心记录当前稳态下保留的最大价值
for (int j = 0, k = 1; j<n&&k<cnt[a[i]]; j++){
if (p[j].l < a[i]){
k++;
res += p[j].d;
}
}
ans = min(ans, s-res);
if (ans == 0) break;
}
printf("%d\n",ans);
}
return 0;
}