您的位置:首页 > 编程语言

编程之美2014格格取数

2014-04-12 13:02 337 查看
根据匈牙利算法解决的思想改写的代码

此题我觉得题意跟数据的有冲突

3 3

1 2 3
3 2 1
2 2 2

上面那段 结果是6的能AC 结果是4的是WA 不晓得是怎么回事。

下面这段代码是根据我的思路写的,但是没有AC

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <climits>
using namespace std;
#define Max 107
int n,n1;
int s[Max][Max];
int p[Max][Max];
int q[Max][Max];
int row[Max], col[Max];
int c1[Max],c2[Max];
int r[Max][Max];
int x[Max],y[Max];
void countZero()
{
memset(row, 0, sizeof(row));
memset(col, 0, sizeof(col));
memset(r, 0, sizeof(r));
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n1; ++j)
{
if (p[i][j] == 0)
row[i]++, col[j]++;
}
}
}

int drawLine()
{
memset(q, 0, sizeof(q));
for (int i = 0; i < n; ++i)
x[i] = 1;
for(int j=0;j<n1;j++)
y[j] = 0;
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n1; ++j)
{
if (r[i][j] == 2)
{
x[i] = 0;
break;
}
}
}
bool is = 1;
while (is)
{
is = 0;
for (int i = 0; i < n; ++i)
{
if (x[i] == 1)
{
for (int j = 0; j < n1; ++j)
{
if (p[i][j] == 0 && y[j] == 0)
{
y[j] = 1;
is = 1;
}
}
}
}
for (int j = 0; j < n1; ++j)
{
if (y[j] == 1)
{
for (int i = 0; i < n; ++i)
{
if (p[i][j] == 0 && x[i] == 0 && r[i][j] == 2)
{
x[i] = 1;
is = 1;
}
}
}
}
}
int line = 0;
for (int i = 0; i < n; ++i)
{
if (x[i] == 0)
{
for (int j = 0; j < n1; ++j)
q[i][j]++;
line++;
}
}
for(int i=0;i<n1;i++)
{
if (y[i] == 1)
{
for (int j = 0; j < n; ++j)
q[j][i]++;
line++;
}
}
return line;
}

int find()
{
countZero();
int zero = 0;
while (1)
{
for (int i = 0; i < n; ++i)
{
if (row[i] == 0)
row[i] = INT_MAX;
}
for(int i=0; i < n1 ;i++)
{
if (col[i] == 0)
col[i] = INT_MAX;
}
bool stop = 1;
if (*min_element(row, row+n) <= *min_element(col, col+n1))
{
int tmp = INT_MAX, index = -1;
for (int i = 0; i < n; ++i)
{
if (tmp > row[i])
tmp = row[i], index = i;
}
int index2 = -1;
for (int i = 0; i < n1; ++i)
if (p[index][i] == 0 && col[i] != INT_MAX)
{
index2 = i;
stop = 0;
zero++;
break;
}
if (stop)
break;
row[index] = col[index2] = INT_MAX;
r[index][index2] = 1;
for (int i = 0; i < n1; ++i)
if (p[index][i] == 0 && col[i] != INT_MAX)
col[i]--;
for (int i = 0; i < n; ++i)
if (p[i][index2] == 0 && row[i] != INT_MAX)
row[i]--;
}
else
{
int tmp = INT_MAX, index = -1;
for (int i = 0; i < n1; ++i)
{
if (tmp > col[i])
tmp = col[i], index = i;
}
int index2 = -1;
for (int i = 0; i < n; ++i)
if (p[i][index] == 0 && row[i] != INT_MAX)
{
index2 = i;
stop = 0;
zero++;
break;
}

if (stop)
break;
row[index2] = col[index] = INT_MAX;
r[index2][index] = 1;

for (int i = 0; i < n1; ++i)
if (p[index2][i] == 0 && col[i] != INT_MAX)
col[i]--;
for (int i = 0; i < n; ++i)
if (p[i][index] == 0 && row[i] != INT_MAX)
row[i]--;
}
}
for (int i = 0; i < n; ++i)
for (int j = 0; j < n1; ++j)
if (p[i][j] == 0)
r[i][j]++;

return zero;
}

int main()
{
int m,l;
scanf("%d",&m);
for(l=1;l<=m;l++)
{
int ans = 0;
scanf("%d%d",&n,&n1);
for (int i = 0; i < n; ++i)
for (int j = 0; j < n1; ++j)
scanf("%d",&s[i][j]);
//  printf("求和最小\n");
for (int i = 0; i < n; ++i)
{for (int j = 0; j < n1; ++j)
//  p[i][j] = *max_element(s[i], s[i]+n)-s[i][j],    //求和最大
p[i][j] = s[i][j]-*min_element(s[i],s[i]+n1);
//printf("%d ",p[i][j]);
// printf("\n");
}     //求和最小
for (int j = 0; j < n1; ++j)
{
int tmp = INT_MAX;
for (int i = 0; i < n; ++i)
{
if (tmp > p[i][j])
tmp = p[i][j];
}
for (int i = 0; i < n; ++i)
p[i][j] -= tmp;
}
/* printf("第一次减小最小值\n");
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < n1; ++j)
printf("%d ",p[i][j]);
printf("\n");
}
*/
while (find() < n&&find()<n1)
{
drawLine();
int min = INT_MAX;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n1; ++j)
if (q[i][j] == 0 && min > p[i][j])
min = p[i][j];

for (int i = 0; i < n; ++i)
for (int j = 0; j < n1; ++j)
if (q[i][j] == 0)
p[i][j] -= min;
else if (q[i][j] == 2)
p[i][j] += min;
}
//    printf("输出划线后的状态\n");
memset(c1,0,sizeof(c1));
memset(c2,0,sizeof(c2));
for (int i = 0; i < n; ++i)
{for (int j = 0; j < n1; ++j)
{
//  printf("%d ",r[i][j]);
if (r[i][j] == 2)
{ans += s[i][j];c1[i]=1;c2[j]=1;}
}
//        printf("\n");
}
if(n>n1)
{
for(int i=0;i<n;i++)
{
if(!c1[i])
{
ans+=*min_element(s[i],s[i]+n1);
}
}
}
if(n<n1)
{
for(int j=0;j<n1;j++)
{
int min2=s[0][j];
if(!c2[j])
{
for(int i=0;i<n;i++)
{
if(min2>s[i][j]) min2=s[i][j];
}
ans+=min2;
}
}
}
printf("Case %d: %d\n",l,ans);
}
return 0;
}
/* 一些输出样例
333
3 3
3 2 1
1 2 3
2 2 2
Case 1: 4
3 1
3
2
1
Case 2: 6
1 3
1 2 3
Case 3: 6
3 3
0 0 0
0 2 1
0 0 0
Case 4: 0
*/



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  2014编程之美