Codeforces 816C/815A - Karen and Game
阿新 • • 發佈:2017-10-28
操作 判斷 spa contest printf define font 技術 大於 行的操作次數為col[j],則有g[i][j]=row[i]+col[j]。如此,求解row[]和col[]數組即可。
傳送門:http://codeforces.com/contest/816/problem/C
本題是一個模擬問題。
有一個n×m的矩陣。最初,這個矩陣為零矩陣O。現有以下操作:
a.行操作“row i”:對第i(1≤i≤n)行的所有元素加一;
b.列操作“col j”:對第j(1≤j≤m)列的所有元素加一。
經過有限次操作,矩陣變為$G=(g_{i,j})_{m*n}$。
對於給定的矩陣G,試判斷G是否可以由零矩陣O通過有限次的“行操作”和“列操作”生成?若可以,則求一個操作步數最小的方案;否則,返回-1。
考慮一個矩陣。假定其首先進行“行操作”,再進行“列操作”。設對第i行的操作次數為row[i],對第j
假設零矩陣O經過“行操作”後變為矩陣T,再由矩陣T經過“列操作”變為矩陣G。則row[i]取矩陣G中第i行的最小元素,col[j]取矩陣G-T中第j行的最小元素。若零矩陣O可以通過row[]和col[]數組對應的操作變為矩陣G,則row[]和col[]數組對應的操作方案為最優操作方案;否則,可行的操作方案不存在。
row[]和col[]數組的求解在程序實現上可以通過逆向模擬的方法。
值得註意的是,對於一個給定行列數目的矩陣,若其行數不大於列數,則首先進行“行操作”,再進行“列操作”是最佳選擇;否則,首先進行“列操作”,再進行“行操作”是最佳選擇。
參考程序如下:
#include <stdio.h> #include <stdlib.h> #define SIZE 100 #define MAX_VAL 1000 int n, m, cnt = 0; int g[SIZE][SIZE]; int row[SIZE], col[SIZE]; void row_operate(void) { for (int i = 0; i < n; i++) { row[i] = MAX_VAL; for (int j = 0; j < m; j++) if (g[i][j] < row[i]) row[i] = g[i][j];for (int j = 0; j < m; j++) g[i][j] -= row[i]; cnt += row[i]; } } void col_operate(void) { for (int j = 0; j < m; j++) { col[j] = MAX_VAL; for (int i = 0; i < n; i++) if (g[i][j] < col[j]) col[j] = g[i][j]; for (int i = 0; i < n; i++) g[i][j] -= col[j]; cnt += col[j]; } } int main(void) { scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) scanf("%d", &g[i][j]); if (n <= m) { row_operate(); col_operate(); } else { col_operate(); row_operate(); } for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) if (g[i][j]) { printf("-1\n"); exit(0); } printf("%d\n", cnt); for (int i = 0; i < n; i++) for (int k = 0; k < row[i]; k++) printf("row %d\n", i + 1); for (int j = 0; j < m; j++) for (int k = 0; k < col[j]; k++) printf("col %d\n", j + 1); return 0; }
Codeforces 816C/815A - Karen and Game