Karen and Game
On the way to school, Karen became fixated on the puzzle game on her phone!
The game is played as follows. In each level, you have a grid with n rows and m columns. Each cell originally contains the number 0.
One move consists of choosing one row or column, and adding 1 to all of the cells in that row or column.
To win the level, after all the moves, the number in the cell at the i-th row and j-th column should be equal to gi, j.
Karen is stuck on one level, and wants to know a way to beat this level using the minimum number of moves. Please, help her with this task!
Input
The first line of input contains two integers, n and m (1 ≤ n, m ≤ 100), the number of rows and the number of columns in the grid, respectively.
The next n lines each contain m integers. In particular, the j-th integer in the i-th of these rows contains gi, j (0 ≤ gi, j ≤ 500).
Output
If there is an error and it is actually not possible to beat the level, output a single integer -1.
Otherwise, on the first line, output a single integer k, the minimum number of moves necessary to beat the level.
The next k lines should each contain one of the following, describing the moves in the order they must be done:
• row x, (1 ≤ x ≤ n) describing a move of the form “choose the x-th row”.
• col x, (1 ≤ x ≤ m) describing a move of the form “choose the x-th column”.
If there are multiple optimal solutions, output any one of them.
Examples
Input
3 5
2 2 2 3 2
0 0 0 1 0
1 1 1 2 1
Output
4
row 1
row 1
col 4
row 3
Input
3 3
0 0 0
0 1 0
0 0 0
Output
-1
這道題的大意就是一個m*n的二維陣列初始為0,問最少經過幾次操作(每次操作可以每一行或每一列對應的每個數加1)得到給出的二維陣列並輸出操作過程(多種可能性輸出任意一種即可)。
如果列數大於行數,說明是一個扁的二維陣列,找到每一行的最小值並記錄(用於對行的輸出),把該行所有數減去這個最小值;現在每一行的每個數之和應該相等,[若不相等輸出-1(證明不能操作成功)]只看第一行進行對列的輸出即可。
如果行數大於列數,說明是一個瘦高的二維陣列,進行類似的操作即可。
#include<iostream>
#include<string.h>
using namespace std;
int grid[510][510];
int mmin[510],sum[510];
int main(){
int col,roo;
while(cin>>roo>>col){
memset(grid,0,sizeof(grid));
memset(sum,0,sizeof(sum));
for(int i=0;i<510;i++)
mmin[i]=9999;
for(int i=0;i<roo;i++)
for(int j=0;j<col;j++)
cin>>grid[i][j];
int chose=max(roo,col);
int ans=0;
if(chose==col){
for(int i=0;i<roo;i++)
for(int j=0;j<col;j++)
if(grid[i][j]<mmin[i]) mmin[i]=grid[i][j];
for(int i=0;i<roo;i++){
ans=ans+mmin[i];
for(int j=0;j<col;j++){
grid[i][j]=grid[i][j]-mmin[i];
sum[i]=sum[i]+grid[i][j];
}
}
for(int i=1;i<roo;i++)
if(sum[i]!=sum[i-1]){
ans=-1;break;
}
if(ans==-1){
cout<<"-1"<<endl;
continue;
}
for(int j=0;j<col;j++){
if(grid[0][j]!=0){
ans=ans+grid[0][j];
}
}
cout<<ans<<endl;
for(int i=0;i<roo;i++){
for(int j=0;j<mmin[i];j++)
cout<<"row "<<i+1<<endl;
}
for(int j=0;j<col;j++){
if(grid[0][j]!=0){
for(int i=0;i<grid[0][j];i++){
cout<<"col "<<j+1<<endl;
}
}
}
}
else{
for(int i=0;i<col;i++)
for(int j=0;j<roo;j++)
if(grid[j][i]<mmin[i]) mmin[i]=grid[j][i];
for(int i=0;i<col;i++){
ans=ans+mmin[i];
for(int j=0;j<roo;j++){
grid[j][i]=grid[j][i]-mmin[i];
sum[i]=sum[i]+grid[j][i];
}
}
for(int i=1;i<col;i++)
if(sum[i]!=sum[i-1]){
ans=-1;break;
}
if(ans==-1){
cout<<"-1"<<endl;
continue;
}
for(int j=0;j<roo;j++){
if(grid[j][0]!=0){
ans=ans+grid[j][0];
}
}
cout<<ans<<endl;
for(int i=0;i<col;i++){
for(int j=0;j<mmin[i];j++)
cout<<"col "<<i+1<<endl;
}
for(int j=0;j<roo;j++){
if(grid[j][0]!=0){
for(int i=0;i<grid[j][0];i++){
cout<<"row "<<j+1<<endl;
}
}
}
}
}
return 0;
}
然而這種寫法程式碼冗長,而且寫迴圈控制位置的時候容易出錯,於是想到了二維陣列的轉置。
#include<iostream>
#include<string.h>
using namespace std;
int grid[510][510];
int temp[510][510];
int mmin[510],sum[510];
int main(){
int col,roo;
while(cin>>roo>>col){
memset(grid,0,sizeof(grid));
memset(sum,0,sizeof(sum));
for(int i=0;i<510;i++)
mmin[i]=9999;
for(int i=0;i<roo;i++)
for(int j=0;j<col;j++)
cin>>temp[i][j];
int chose=max(roo,col);
int ans=0;
int det=0;
if(chose==roo){
//轉置並交換行列數 併為轉置變數賦值為1
for(int i=0;i<roo;i++)
for(int j=0;j<col;j++)
grid[j][i]=temp[i][j];
int tttemp=col;col=roo;roo=tttemp;
det=1;
}
else
for(int i=0;i<roo;i++)
for(int j=0;j<col;j++)
grid[i][j]=temp[i][j];//直接賦值過去
//開始計算
for(int i=0;i<roo;i++)
for(int j=0;j<col;j++)
if(grid[i][j]<mmin[i]) mmin[i]=grid[i][j];
for(int i=0;i<roo;i++){
ans=ans+mmin[i];
for(int j=0;j<col;j++){
grid[i][j]=grid[i][j]-mmin[i];
sum[i]=sum[i]+grid[i][j];
}
}
for(int i=1;i<roo;i++)
if(sum[i]!=sum[i-1]){
ans=-1;break;
}
if(ans==-1){
cout<<"-1"<<endl;
continue;
}
for(int j=0;j<col;j++){
if(grid[0][j]!=0){
ans=ans+grid[0][j];
}
}
cout<<ans<<endl;
for(int i=0;i<roo;i++){
for(int j=0;j<mmin[i];j++)
det?cout<<"col "<<i+1<<endl:cout<<"row "<<i+1<<endl; //判斷是否轉置過 控制相應輸出 注意這裡是i
}
for(int j=0;j<col;j++){
if(grid[0][j]!=0){
for(int i=0;i<grid[0][j];i++){
det?cout<<"row "<<j+1<<endl:cout<<"col "<<j+1<<endl;//判斷是否轉置過 控制相應輸出 注意這裡是j
}
}
}
}
return 0;
}