【FJOI2014】石子合并问题
2014-03-31 19:26
281 查看
问题描述
有n堆石子,每堆1个,要合并成一堆,规定每次可以任意选两堆合并成新的一堆,两堆中较少的石子数记为该次合并的得分。
输入n
输出最大得分
样例输入 7
样例输出 9
O(n)做法
#include<cstdio>
using namespace std;
int n,f[20001];
int main()
{
scanf("%d",&n);
for(int i=2;i<=n;i++){
if(i&1)
f[i]=f[i>>1]+f[(i>>1)+1];
else f[i]=(f[i>>1]<<1);
f[i]+=(i>>1);
}
printf("%d",f
);
return 0;
}O(nlogn)堆
#include<cstdio>
#include<queue>
long long n,ans=0;
using namespace std;
int main()
{
priority_queue<long long,vector<long long>,greater<long long> > q;
scanf("%d",&n);
for(int i=1;i<=n;i++)q.push(1);
for(int i=1;i<=n-1;i++)
{
int x=q.top();q.pop();
int y=q.top();q.pop();
ans+=min(x,y);
q.push(x+y);
}
printf("%d",ans);
return 0;
}
有n堆石子,每堆1个,要合并成一堆,规定每次可以任意选两堆合并成新的一堆,两堆中较少的石子数记为该次合并的得分。
输入n
输出最大得分
样例输入 7
样例输出 9
O(n)做法
#include<cstdio>
using namespace std;
int n,f[20001];
int main()
{
scanf("%d",&n);
for(int i=2;i<=n;i++){
if(i&1)
f[i]=f[i>>1]+f[(i>>1)+1];
else f[i]=(f[i>>1]<<1);
f[i]+=(i>>1);
}
printf("%d",f
);
return 0;
}O(nlogn)堆
#include<cstdio>
#include<queue>
long long n,ans=0;
using namespace std;
int main()
{
priority_queue<long long,vector<long long>,greater<long long> > q;
scanf("%d",&n);
for(int i=1;i<=n;i++)q.push(1);
for(int i=1;i<=n-1;i++)
{
int x=q.top();q.pop();
int y=q.top();q.pop();
ans+=min(x,y);
q.push(x+y);
}
printf("%d",ans);
return 0;
}
相关文章推荐
- ccf 2016-12-4 压缩编码 石子合并问题
- NK1137 石子合并问题
- 经典问题石子合并(环形)DP
- BZOJ 4016: [FJOI2014]最短路径树问题( 最短路 + 点分治 )
- 石子合并问题汇总
- 石子合并问题
- bzoj 4016 [FJOI2014]最短路径树问题(最短路径树+树分治)
- 石子合并问题 (朴素区间DP&&GarsiaWachs算法)
- 石子合并问题
- 石子合并问题--圆形版(区间DP)
- 4016: [FJOI2014]最短路径树问题 点分治
- HRBUST 1819 石子合并问题--圆形版
- 石子合并问题(区间DP)
- 【BZOJ4016】[FJOI2014]最短路径树问题 最短路径树+点分治
- 石子合并问题
- 石子合并问题
- SSL_1597 石子合并问题
- 合并石子问题 贪心+最大最小堆基本操作
- 石子(环形)合并问题_dp
- 【BZOJ4016】【FJOI2014】 最短路径树问题 树的点分治