天天看點

H. Degenerate Matrix 序列變換

H. Degenerate Matrix time limit per test  1 second memory limit per test  256 megabytes input  standard input output  standard output

The determinant of a matrix 2 × 2 is defined as follows:

H. Degenerate Matrix 序列變換

A matrix is called degenerate if its determinant is equal to zero.

The norm ||A|| of a matrix A is defined as a maximum of absolute values of its elements.

You are given a matrix 

H. Degenerate Matrix 序列變換

. Consider any degenerate matrix B such that norm ||A - B|| is minimum possible. Determine||A - B||.

Input

The first line contains two integers a and b (|a|, |b| ≤ 109), the elements of the first row of matrix A.

The second line contains two integers c and d (|c|, |d| ≤ 109) the elements of the second row of matrix A.

Output

Output a single real number, the minimum possible value of ||A - B||. Your answer is considered to be correct if its absolute or relative error does not exceed 10 - 9.

Sample test(s) input

1 2
3 4
      

output

0.2000000000
      

input

1 0
0 1
      

output

0.5000000000
      

Note

In the first sample matrix B is 

H. Degenerate Matrix 序列變換

In the second sample matrix B is 

H. Degenerate Matrix 序列變換

覺得很好的一道題,題目連結:http://codeforces.com/contest/549/problem/H

題意:

給你一個2*2的矩陣A,讓你構造一個矩陣B,矩陣B要滿足兩條對角線元素相乘結果相等,使得 ||A-B|| 值最小。||X||表示矩陣X中的4個元素中值最大的元素。

分析:

枚舉增量(發現有很多二分都是枚舉增量的),判斷是否符合條件,然後縮小範圍。

code:

[cpp]  view plain  copy

  1. #include<bits/stdc++.h>  
  2. using namespace std;  
  3. typedef long double LD;  
  4. int a, b, c, d;  
  5. LD f1(int m1, int m2, LD x)  
  6. {  
  7.     return max(max((m1+x)*(m2+x),(m1+x)*(m2-x)),max((m1-x)*(m2+x),(m1-x)*(m2-x)));  
  8. }  
  9. LD f2(int m1, int m2, LD x)  
  10. {  
  11.     return min(min((m1+x)*(m2+x),(m1+x)*(m2-x)),min((m1-x)*(m2+x),(m1-x)*(m2-x)));  
  12. }  
  13. int Check(LD x)  
  14. {  
  15.     LD pr = f1(a,d,x); //(a..)*(d..) 與 (c..)*(b..) 比較,把它比作第一段和第二段,然後進行比較,是否會有等值情況  
  16.     LD pl = f2(a,d,x);  
  17.     LD qr = f1(c,b,x);  
  18.     LD ql = f2(c,b,x);   
  19.     if(pr < ql || qr < pl) return 0; //如果第一段與第二段不相交,則擴大兩邊使其可能相交  
  20.     else return 1; //如果已經相交,那麼減小增量x使得兩邊縮小,更靠近結果  
  21. } //這裡我說得相交是将最大值與最小值看做兩個點,連成的一條線段,最後兩條線段的位置關系(yy的。。)  
  22.   //相交的部分代表值相等  
  23. int main()  
  24. {  
  25.     scanf("%d%d%d%d", &a,&b,&c,&d);  
  26.     LD l=0, r=1e10;  
  27.     for(int i=0; i<200; i++)  
  28.     {  
  29.         LD mid = 0.5*(l+r);  
  30.         if(Check(mid)) r = mid;  
  31.         else l = mid; //增量x增大,那麼結果的兩邊(最大值與最小值)會相應往兩邊擴(更大、更小)  
  32.     }  
  33.     printf("%.10f\n", (double)(0.5*(l+r)));  
  34.     return 0;  
  35. }  

做完上面這道題後,把本來一直不會做的下面這道題給秒了。。

題目連結: http://acm.hdu.edu.cn/showproblem.php?pid=5248

序列變換

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 625    Accepted Submission(s): 305

Problem Description 給定序列 A={A1,A2,...,An} , 要求改變序列A中的某些元素,形成一個嚴格單調的序列B(嚴格單調的定義為: Bi<Bi+1,1≤i<N )。

我們定義從序列A到序列B變換的代價為 cost(A,B)=max(|Ai−Bi|)(1≤i≤N) 。

請求出滿足條件的最小代價。

注意,每個元素在變換前後都是整數。  

Input 第一行為測試的組數 T(1≤T≤10) .

對于每一組:

第一行為序列A的長度 N(1≤N≤105) ,第二行包含N個數, A1,A2,...,An .

序列A中的每個元素的值是正整數且不超過 106 。  

Output 對于每一個測試樣例,輸出兩行:

第一行輸出:"Case #i:"。i代表第 i 組測試資料。

第二行輸出一個正整數,代表滿足條件的最小代價。  

Sample Input

2
2
1 10
3
2 5 4
               

Sample Output

Case #1:
0
Case #2:
1
         
         

               

code: [cpp]  view plain  copy

  1. #include<stdio.h>  
  2. int T, n, a[100010], b[100010];  
  3. bool Check(int x)  
  4. {  
  5.     for(int i=0; i<n; i++) b[i] = a[i];  
  6.     b[0] -= x;  
  7.     for(int i=1; i<n; i++)  
  8.     {  
  9.         int temp1 = b[i-1]-b[i]+1;  
  10.         int temp2 = b[i]-b[i-1]-1;  
  11.         if(b[i] <= b[i-1])  
  12.         {  
  13.             if(temp1 > x) return false;  
  14.             else b[i] = b[i-1]+1;  
  15.         }  
  16.         else  
  17.         {  
  18.             if(temp2 <= x) b[i] = b[i-1]+1;  
  19.             else b[i] -= x;  
  20.         }  
  21.     }  
  22.     return true;  
  23. }  
  24. int main()  
  25. {  
  26.     scanf("%d", &T);  
  27.     for(int t=1; t<=T; t++)  
  28.     {  
  29.         scanf("%d", &n);  
  30.         for(int i=0; i<n; i++)  
  31.             scanf("%d", a+i);  
  32.         int l = 0, r = 1e6, mid;  
  33.         for(int i=0; i<20; i++)  
  34.         {  
  35.             mid = (l+r)/2;  
  36.             if(Check(mid)) r = mid;  
  37.             else l = mid;  
  38.         }  
  39.         printf("Case #%d:\n%d\n", t,r);  
  40.     }  
  41.     return 0;  
  42. }