1. 程式人生 > >uvalive 3029 City Game

uvalive 3029 City Game

https 參考 city game 距離 != return pre 輸入 子矩陣

https://vjudge.net/problem/UVALive-3029

題意:

給出一個只含有F和R字母的矩陣,求出全部為F的面積最大的矩陣並且輸出它的面積乘以3。

思路:

求面積最大的子矩陣,可以用掃描線。參考訓練指南(orz,雖然並不知道為什麽用掃描線)。

對於每一個格子包含F,我們可以把它向上拉成一條懸線,直到上面的格子為R,然後觀察這條懸線可以掃到左邊與右邊的最大距離,那麽我們所求的面積就是所有的懸線中 懸線的長度乘以(右邊界 - 左邊界 + 1)的最大值。

然後,需要計算懸線的長度,用up來表示,那麽當這個格子為F時up(i,j) = up(i - 1,j) + 1(i >= 1),up(i,j) = 1,(i == 0);

當這個格子為R時,up(i,j) = 0。

然後,用left數組和right數組維護左右邊界的信息:

我們假設lo是當前格子之前的最近的是R的格子,從左往右遍歷,那麽 lo 的初值是-1,那麽當(i,j) 為 F時 ,left(i,j) = max(left(i-1,j),lo + 1),為什麽呢,因為當前的懸線如果是包含上一行此列的格子的話,那麽就要考慮上一行左邊的情況了;

當(i,j)為R時,left(i,j) = 0。

維護右邊界的信息同理,不同的是求最小值和從右往左遍歷。

!!!:記住一邊遍歷,一邊維護。輸入也是坑!

代碼:

  1 #include <stdio.h>
  2
#include <string.h> 3 #include <algorithm> 4 using namespace std; 5 6 char a[1005][1005]; 7 int up[1005][1005],right[1005][1005],left[1005][1005]; 8 9 int main() 10 { 11 int t; 12 13 scanf("%d",&t); 14 15 while(t--) 16 { 17 int m,n; 18
19 memset(a,0,sizeof(a)); 20 memset(up,0,sizeof(up)); 21 memset(right,0,sizeof(right)); 22 memset(left,0,sizeof(left)); 23 24 scanf("%d%d",&m,&n); 25 26 getchar(); 27 28 for (int i = 0;i < m;i++) 29 for (int j = 0;j < n;j++) 30 { 31 char s; 32 33 s = getchar(); 34 35 while (s != R && s != F) s = getchar(); 36 37 if (s == R) a[i][j] = 0; 38 else a[i][j] = 1; 39 } 40 41 /*for (int i= 0;i < m;i++) 42 { 43 for (int j = 0;j < n;j++) printf("%d",(int)a[i][j]); 44 45 printf("\n"); 46 }*/ 47 48 int ans = 0; 49 50 for (int i = 0;i < m;i++) 51 { 52 for (int j = 0;j < n;j++) 53 { 54 if (i == 0) 55 { 56 up[i][j] = a[i][j]; 57 } 58 else 59 { 60 if (a[i][j]) up[i][j] = up[i-1][j] + 1; 61 else up[i][j] = 0; 62 } 63 } 64 65 int lo = -1,ro = n; 66 67 if (i == 0) 68 { 69 for (int j = 0;j < n;j++) 70 { 71 if (a[i][j] == 0) left[i][j] = 0, lo = j; 72 else left[i][j] = lo + 1; 73 } 74 75 for (int j = n - 1;j >= 0;j--) 76 { 77 if (a[i][j] == 0) right[i][j] = n, ro = j; 78 else right[i][j] = ro - 1; 79 } 80 81 for (int j = 0;j < n;j++) 82 { 83 int tmp = up[i][j] * (right[i][j] - left[i][j] + 1); 84 85 ans = max(ans,tmp * 3); 86 } 87 } 88 else 89 { 90 for (int j = 0;j < n;j++) 91 { 92 if (a[i][j] == 0) left[i][j] = 0, lo = j; 93 else left[i][j] = max(lo + 1,left[i-1][j]); 94 } 95 96 for (int j = n - 1;j >= 0;j--) 97 { 98 if (a[i][j] == 0) right[i][j] = n, ro = j; 99 else right[i][j] = min(ro - 1,right[i-1][j]); 100 } 101 102 for (int j = 0;j < n;j++) 103 { 104 int tmp = up[i][j] * (right[i][j] - left[i][j] + 1); 105 106 ans = max(ans,tmp * 3); 107 } 108 } 109 } 110 111 /*for (int i = 0;i < m;i++) 112 { 113 for (int j = 0;j < n;j++) 114 { 115 printf("%d %d %d\n",up[i][j],left[i][j],right[i][j]); 116 } 117 }*/ 118 119 printf("%d\n",ans); 120 } 121 122 return 0; 123 }

uvalive 3029 City Game