随笔-38  评论-23  文章-0  trackbacks-0

:题目例子:http://acm.zjgsu.edu.cn/JudgeOnline/showproblem?problem_id=1277
题目的大意是:
有N个房子在一条街上,(街是条直线)每个房子有个离这个街的最末端得距离。现在要在这条街上安装m个路由器 使得每个房子都能有个距离最近的路由器。并且使得所有房子和它距离最近的路由器之间的距离最大一个是最小的。
初一想就是 一个经典DP问题..
比如考虑 两个房子 一个路由器.肯定是将路由器放在中间位置..
于是对房子的距离排个序 就可以很快得出一个DP的表达式。
F[i,k]表示前i个房子放k个路由器的最优解..
则F[i,k]=min{max(F[j,k-1],(house[i]-house[j+1])/2),1<=j<i}
表示前j个房子放k-1路由器,第K个路由器放在第j+1和第i个房子的中点..
算法是O(m*n^2) 对于数据两n<=100000 无论如何都优化不了的DP 已经难以解决这个问题了..
后来经同实验室的朋友介绍了一个算法参数搜索的应用..
并找到一个论文.http://acm.zjgsu.edu.cn/Software/canshusousuo.doc(汪汀 著) 转载至中华信息网

关于怎么解这个问题就不多说了..就是找最优解.首先找一个最小的解,最大解,然后二分判断这个某个解是否是可行解。

代码如下:

#include<iostream>
#include
<algorithm>
using namespace std;
int house[100002];
int n,m;
bool isok(int value)
{
    
int i=1,j,p=1;
    
for(j=1;j<=n;j++)
    
{
                
if(i>m) return false;
        
if((house[j]-house[p])*10>value*2)
        
{
            p
=j;
            i
++;
        }

    }

    
if(i<=m)
        
return true;
    
return false;
}

void AC()
{
    
int ans;
    
int low=0,hight=(house[n]-house[0])*10,mid;
    
while(low<=hight)
    
{
        mid
=(low+hight)/2;
        
if(isok(mid))
            hight
=mid-1;
        
else
            low
=mid+1;
    }

    
if(isok(low))
        ans
=low;
    
else
        ans
=hight;
    printf(
"%.1lf\n",ans*1.0/10);
}

int main()
{
    
int T;
    scanf(
"%d",&T);
    
while(T--)
    
{
        scanf(
"%d%d",&m,&n);
        
for(int i=1;i<=n;i++)
            scanf(
"%d",&house[i]);
        house[
0]=0;
        sort(house,house
+n+1);
        AC();
    }

}

posted on 2009-04-12 12:41 米游 阅读(1660) 评论(2)  编辑 收藏 引用 所属分类: ACM

评论:
# re: 参数搜索(求最优解问题) 2009-04-12 19:17 | winsty
max-min问题大都是这么搞的 做多了就有感觉了...  回复  更多评论
  
# re: 参数搜索(求最优解问题)[未登录] 2009-04-30 11:16 | will
顶一个~  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理