#6030. 【雅禮集訓 2017 Day1】矩陣
阿新 • • 發佈:2017-09-05
line 字符 oid inline 技術分享 任務 有一種 run -h
#6030. 「雅禮集訓 2017 Day1」矩陣
題目描述
有一個 n×n 的矩陣,每個位置 (i,j) 如果是 .
表示為白色,如果是 #
表示為黑色。
初始時,每個位置可以是黑色或白色的,(i,j) 位置的值會作為 ai,j 給你。
現在有一種操作,選擇兩個整數 i,j∈[1,n],記 (i,1),(i,2),…,(i,n) (i, 1), (i, 2)的顏色為 C1,C2,…Cn ??,將 (1,j),(2,j),…,(n,j) 的顏色賦為 C1,C2,…,Cn ??。
你的任務是將整個矩陣變成全黑,如果能夠辦到,輸出最少步數,否則輸出 −1。
輸入格式
第一行一個整數 n nn。 接下來 n nn 行,每行 n nn 個字符表示整個矩陣。
輸出格式
輸出只有一行,一個整數表示答案。
樣例
樣例輸入 1
2
#.
.#
樣例輸出 1
3
樣例輸入 2
2
..
..
樣例輸出 2
-1
數據範圍與提示
對於 30% 的數據,n≤4
對於另外 20%的數據,滿足每一列都至少有一個黑色的格子; 對於 100% 的數據,1≤n≤1000
很巧妙地思路 應該是貪心吧。。
首先我們模擬一下可以發現
想要把整張圖塗黑 一定是先塗黑一行之後 再塗整張圖
塗黑一列的代價最小只能為1
那麽我們可以想辦法先用最少的步數塗黑一行
再用這一行去塗改其他列
塗改一行的最少步數 無非就是這一行的白點數
但是有一種特殊情況
像這樣 (3,3) 這個位置不可能一次就塗成黑色
即你用的 第i行 對應的 第i列 沒有一個黑點
這時候需要多加一步
先用第3行對第3列染色
然後再用 第1行 或 第2行 把(3,3)這個位置塗黑
無論是 第1行 還是 第2行 (3,1)和(3,2) 一定會又變成白色 這不影響我們的程序
因為中間那一步一定會被後來的一步給覆蓋
這就是特殊情況多加一步
之後統計還有多少列 存在白點 用全黑的一行塗改就好了
1 #include <cstdio> 2 #include <cctype> 3 4 const int MAXN=1010; 5 6 int n; 7 8 char s[MAXN]; 9 10 int map[MAXN][MAXN],h[MAXN],l[MAXN]; 11 12 bool flag; 13 14 inline void read(int&x) { 15 int f=1;register char c=getchar(); 16 for(x=0;!isdigit(c);c==‘-‘&&(f=-1),c=getchar()); 17 for(;isdigit(c);x=x*10+c-48,c=getchar()); 18 x=x*f; 19 } 20 21 inline int min(int a,int b) {return a<b?a:b;} 22 23 inline void running() { 24 int ans=0x3f3f3f3f; 25 for(int i=1;i<=n;++i) 26 ans=min(ans,n-h[i]+(l[i]==0));//用最少的步數將一行轉化成黑色 27 for(int i=1;i<=n;++i) 28 if(l[i]!=n) ++ans;//還有哪列沒有塗黑 29 printf("%d\n",ans); 30 return; 31 } 32 33 int hh() { 34 read(n); 35 for(int i=1;i<=n;++i) { 36 scanf("%s",s+1); 37 for(int j=1;j<=n;++j) 38 if(s[j]==‘#‘) { 39 flag=true; 40 ++h[i]; 41 ++l[j]; 42 } 43 } 44 if(!flag) printf("-1\n"); 45 else running(); 46 return 0; 47 } 48 49 int sb=hh(); 50 int main(int argc,char**argv) {;}代碼
#6030. 【雅禮集訓 2017 Day1】矩陣