本文主要是对2014微软编程之美的一道题(格格取数)的解答,用的是贪心算法。问题如下:
给你一个m x n (1 <= m, n <= 100)的矩阵A (0<=aij<=10000),要求在矩阵中选择一些数,要求每一行,每一列都至少选到了一个数,使得选出的数的和尽量的小。
本算法主要分两步,作简要说明:1、为了是每行每列都去到,我们分别对每行每列取最小值;2、在取得这些数值中可能存在多余的数值,对于这些数值我们进行两种处理:(1)看看可不可以直接删除,(2)看看可不可以进行转换
-
#include <iostream>
-
#include <vector>
-
#include <map>
-
-
using namespace std;
-
-
int row,col;
-
vector<int> m_row,m_col;
-
vector<vector<int> >matrix;
-
vector<vector<bool> >mark;
-
multimap<int,vector<pair<size_t,size_t> > >delete_map;
-
-
void find_row_min_num(void){
-
for(int i=0;i<row;++i){
-
vector<int>& tmp_arr = matrix[i];
-
int tmp = matrix[i][0];
-
int k = 0;
-
for(int j=0;j<col;++j){
-
if(tmp > tmp_arr[j]){
-
tmp = tmp_arr[j];
-
k = j;
-
}
-
}
-
mark[i][k] = true;
-
//min_num.insert(make_pair(tmp,i*row+k));
-
}
-
}
-
-
void find_col_min_num(void){
-
for(int j=0;j<col;++j){
-
int tmp = matrix[0][j];
-
int k = 0;
-
for(int i=0;i<row;++i){
-
if(tmp > matrix[i][j]){
-
tmp = matrix[i][j];
-
k = i;
-
}
-
}
-
if(false == mark[k][j]){
-
mark[k][j] = true;
-
//min_num.insert(make_pair(tmp,k*row+j));
-
}
-
}
-
}
-
void mark_fix(int i,int pre){
-
//首先检查是否可以直接删除
-
for(int k=0;k<row;++k){
-
if(mark[k][pre] && k != i){
-
mark[i][pre] = false;
-
return;
-
}
-
}
-
-
for(int ii=i+1;ii<row;++ii){
-
if(mark[ii][pre])
-
continue;
-
if(matrix[ii][pre] == matrix[i][pre]){//同一列中有相同的最小值
-
for(int jj=0;jj<col;++jj){
-
if(mark[ii][jj]){
-
for(int iii=0;iii<row;++iii){//看看栓出此列是否合法
-
if(mark[iii][jj]){
-
if(iii != ii){
-
mark[ii][jj] = false;
-
mark[i][pre] = false;
-
mark[ii][pre] = true;
-
return;
-
}
-
}
-
}
-
}
-
}
-
}
-
}
-
}
-
-
void check_row(void){
-
for(int i=0;i<row;++i){
-
int pre = -1;
-
for(int j=0;j<col;++j){
-
if(mark[i][j]){
-
if(-1 != pre){
-
mark_fix(i,pre);
-
}
-
pre = j;
-
}
-
}
-
int count =0;
-
for(int k=0;k<col;++k){
-
if(mark[i][k])
-
++count;
-
}
-
if(count>1)
-
mark_fix(i,pre);
-
}
-
}
-
void delete_elem(void){
-
check_row();
-
}
-
void check_row_and_col(void){
-
for(int i=0;i<row;++i){
-
bool b = false;
-
for(int j=0;j<col;++j){
-
if(mark[i][j])
-
if(!b)
-
b = true;
-
else{
-
m_row.push_back(i);
-
break;
-
}
-
}
-
}
-
-
for(int i=0;i<col;++i){
-
bool b = false;
-
for(int j=0;j<row;++j){
-
if(mark[j][i])
-
if(!b)
-
b = true;
-
else{
-
m_col.push_back(i);
-
break;
-
}
-
}
-
}
-
}
-
void fix_matrix(void){
-
check_row_and_col();
-
if(m_row.empty() || m_col.empty())
-
return;
-
for(size_t i=0;i<m_row.size();++i){
-
int max_num = 0;
-
int tmp_row = m_row[i];
-
vector<pair<size_t,size_t> > pairs;
-
for(int k=0;k<col;++k){
-
if(mark[tmp_row][k]){
-
int tmp = matrix[tmp_row][k];
-
for(size_t j=0;j<m_col.size();++j){
-
int tmp_col = m_col[j];
-
for(int kk=0;kk<row;++kk){
-
if(mark[kk][tmp_col]){
-
if(kk!=tmp_row && k!=tmp_col){
-
int a1 = matrix[kk][k];
-
int a2 = matrix[tmp_row][k];
-
int a3 = matrix[kk][tmp_col];
-
if(a1< a2+a3 && a2+a3-a1 > max_num){
-
max_num = a2+a3-a1;
-
pairs.clear();
-
pairs.push_back(make_pair(tmp_row,k));
-
pairs.push_back(make_pair(kk,tmp_col));
-
}
-
}
-
}
-
}
-
}
-
}
-
}
-
if(!pairs.empty())
-
delete_map.insert(make_pair(max_num,pairs));
-
}
-
}
-
bool adjust_elem(void){
-
if(delete_map.empty()){
-
delete_elem();
-
return true;
-
}
-
else{
-
for(multimap<int,vector<pair<size_t,size_t> > >::reverse_iterator riter = delete_map.rbegin();
-
riter != delete_map.rend();++riter){
-
vector<pair<size_t,size_t> > tmp= riter->second;
-
size_t a1 = tmp[0].first;
-
size_t a2 = tmp[0].second;
-
size_t a3 = tmp[1].first;
-
size_t a4 = tmp[1].second;
-
if(mark[a1][a4])
-
if(matrix[a1][a2]+matrix[a3][a4]-matrix[a3][a2]<matrix[a1][a4]){
-
mark[a1][a4] = false;
-
continue;
-
}
-
if(mark[a1][a2] && mark[a3][a4]){
-
mark[a1][a2] = mark[a3][a4] = false;
-
mark[a3][a2] =true;
-
}
-
}
-
delete_map.clear();
-
m_row.clear();
-
m_col.clear();
-
return false;
-
}
-
}
-
void find_min_sum(){
-
find_row_min_num();
-
find_col_min_num();
-
-
bool b = false;
-
while(!b){
-
fix_matrix();
-
b = adjust_elem();
-
}
-
}
-
int every_group(void){
-
cin>>row>>col;
-
for(int i=0;i<row;++i){
-
vector<int>tmp_arr;
-
vector<bool>tmp_mark;
-
for(int j=0;j<col;++j){
-
int tmp=0;
-
cin>>tmp;
-
tmp_arr.push_back(tmp);
-
tmp_mark.push_back(false);
-
}
-
matrix.push_back(tmp_arr);
-
mark.push_back(tmp_mark);
-
}
-
-
find_min_sum();
-
-
int sum=0;
-
for(int i=0;i<row;++i){
-
for(int j=0;j<col;++j){
-
if(true == mark[i][j]){
-
sum += matrix[i][j];
-
}
-
}
-
}
-
matrix.clear();
-
mark.clear();
-
m_row.clear();
-
m_col.clear();
-
row=col=0;
-
return sum;
-
}
-
int main(){
-
int group_num;
-
cin>>group_num;
-
vector<int> vec;
-
for(int i=0;i<group_num;++i)
-
vec.push_back(every_group());
-
-
for(size_t i=0;i< vec.size();++i){
-
std::cout<<"Case "<<i+1<<": "<<vec[i]<<endl;
-
}
-
-
return 0;
-
}
阅读(4073) | 评论(2) | 转发(0) |