首页 > 代码库 > HDU 4923 Room and Moor
HDU 4923 Room and Moor
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4923
解题报告:给出一个长度为n的只包含0和1的序列,是否存在一个序列Bi满足一下条件:
1. 0 <= B[i] <= 1
2. B[i] <= B[i+1]
3. f(A,B) = ∑(i=1-n) (A[i] - B[i])^2
4. f(A,B)最小是多少
前面的0可以直接去掉,后面的1可以直接去掉,然后剩下中间形如1 1 0 0的序列,在这样的区间中前后的B[i]很明显应该是相等才能保证最小的,
我们可以先分别求出每段这样的区间的B[i],然后维护一个单调队列,当要插入的B[i]大于等于队尾的B[i],则直接插入,当要插入的小于队尾的B[i],
则将队尾的那个区间跟现在要插入的区间合并然后求出一个新的B[i]代替,得到新的B[i]之后注意又要跟队尾比较。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<deque> 6 using namespace std; 7 #define maxn 100005 8 struct node 9 {10 int a,b;11 double x;12 }B[maxn];13 int A[maxn];14 deque<node> que;15 int main()16 {17 int T,n;18 scanf("%d",&T);19 while(T--)20 {21 scanf("%d",&n);22 for(int i = 1;i <= n;++i)23 scanf("%d",&A[i]);24 while(n >= 1 && A[n] == 1) //把后面的1去掉 25 n--;26 int s = 1;27 while(s <= n && A[s] == 0)28 s++;29 if(s >= n)30 {31 printf("%.6lf\n",0);32 continue;33 }34 A[0] = 0;35 int f = 0;36 for(int i = s;i <= n;++i)37 {38 if(A[i] == 1)39 {40 if(A[i-1] == 0 && A[i] == 1)41 {42 f++;43 B[f].a = B[f].b = 0; //初始化 44 45 }46 B[f].a++;47 }48 else B[f].b++;49 50 }51 for(int i = 1;i <= f;++i) //遍历一遍,计算出每节的x应该是多少 52 B[i].x = (double)B[i].a / (double)(B[i].a + B[i].b);53 54 // for(int i = 1;i <= f;++i)55 // printf("a = %d b = %d x = %.6lf\n",B[i].a,B[i].b,B[i].x);56 que.clear();57 node temp;58 deque<node>::iterator iter;59 for(int i = 1;i <= f;++i) //维护一个单调队列 60 {61 if(que.empty() || B[i].x >= que.begin()->x)62 que.push_front(B[i]);63 else64 {65 while(!que.empty() && B[i].x < que.begin()->x)66 {67 B[i].a += que.begin()->a;68 B[i].b += que.begin()->b;69 B[i].x = (double)B[i].a / (double)(B[i].a + B[i].b);70 que.pop_front();71 }72 i--; //为了在下一次循环中,把这个节点插入到队列中 73 }74 }75 double tot = 0;76 for(iter = que.begin();iter != que.end();++iter)77 tot += ((double)iter->a * (1.0 - iter->x) * (1.0 - iter->x) + (double)iter->b * iter->x * iter->x);78 printf("%.6lf\n",tot);79 }80 return 0;81 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。