poj3273
来源:互联网 发布:厦门广电网络 电话多少 编辑:程序博客网 时间:2024/06/06 10:06
题目还是有思维量的。大致题意为给定n个整数,要求分成m组,求出各种组合方式中每组最大的和的最小值。那么这题,最开始想到的依然是暴力。枚举所有可能的组合方式,加上剪枝,TLE。于是想用二分查找法求解单调函数。思路如下:
选定一个数x,将n个数按照每组最大x且组合个数最小的方式组合(贪心法求解对于每个x的最小组合个数)
1)如果最小组合个数大于m,则说明x的值一定小于要求的值,不满足要求
2)如果最小组合个数小于或等于m,则说明满足要求,可以组成m组,但是必须为这些数中的最小值。
而x的取值范围为min(record[i])——sum(record[i])(包括min,sum)。同时,用这些数按照上述方式组合,其最小组合个数单调递减(不严格单调递减),我们只需要用二分查找寻找出满足最小组合个数<=m的第一个数就可以了。下面是代码:
先给出dfs+剪枝代码(TLE):
#include<stdio.h>#include<stdlib.h>#define Max 100010#define Maxx(a,b) (a)>(b)?(a):(b)#define Inf 1000000010int record[Max];int n,m;int Sum;void dfs(int index,int num,int inf){//if(inf>=Sum)//return ;if(index==m){int temp=0;for(int i=num;i<=n;i++)temp+=record[i];temp=Maxx(temp,inf);if(temp<Sum)Sum=temp;return ;}int temp=0;for(int i=num;i<=n-(m-index);i++){temp+=record[i];int t=Maxx(inf,temp);if(t>=Sum)return ;dfs(index+1,i+1,t);}}int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&record[i]);Sum=Inf;dfs(1,1,0);printf("%d\n",Sum);return 0;}
下面是二分查找求单调函数代码: 524K+63MS
#include <stdio.h>#include <stdlib.h>#define Max 100010 //最大个数int record[Max];int n,m;int main(){while(scanf("%d%d",&n,&m)!=EOF){int INf=0,Sum=0;for(int i=1;i<=n;i++){ scanf("%d",&record[i]);if(record[i]>INf)INf=record[i]; //求最大值Sum+=record[i]; // 最和}int left=INf,right=Sum,mid; //在INf和Sum之间用二分查找法求解单调函数while(left<=right){mid=(left+right)>>1; int temp=0,num=1;for(int i=1;i<=n;i++){ //贪心法求以mid为最大上限按上述组合方式组合的最小组合个数 temp+=record[i];if(temp>mid){num++;if(num>m)break;temp=record[i];}}if(num>m) //若个数大于m,则说明mid不够大left=mid+1;else if(num<=m) // 求解满足要求的最小值right=mid-1;}printf("%d\n",mid); // 输出最小值}return 0;}
0 0
- poj3273
- poj3273
- poj3273
- poj3273
- poj3273
- poj3273
- poj3273
- poj3273
- poj3273
- POJ3273
- poj3273
- poj3273
- poj3273
- POJ3273
- poj3273 二分
- POJ3273 二分
- 【POJ3273】二分
- poj3273解题报告
- SqlHelper.cs
- Redis01总纲
- BroadcastReceiver
- 环境变量的配置
- MySQL 学习笔记 一
- poj3273
- classpath
- Cocos2d-X研究之v3.x 事件分发机制详解
- 杭电 1262 寻找素数对
- 手电筒项目源代码
- .net连接MySQL的方法
- C#实现POST提交方式
- 发短信
- hadoop执行时将输入文件复制到hdfs时的错误