题目大意:
现有T个测例,每个测例中都给定一个大小为N(small:1 ≤ N ≤ 8,large:1 ≤ N ≤ 40)的正方形矩阵,矩阵只有0或1,现只有一种操作,就是交换任意两行,现对于每个测例都要求出最少交换多少次可以使得所有1都位于主对角线或主对角线以下,现保证每个输入测例都是有解的。
注释代码:
/*
* Problem ID : GCJ Round 2 2009 Problem A. Crazy Rows
* Author : Lirx.t.Una
* Language : GCC
*/
#include <stdio.h>
//矩阵宽度的最大值
#define MAXN 40
char m[MAXN][MAXN];//matrix,矩阵
char pos[MAXN];//pos[i]表示第i行最后一个1出现的位置(下标从0开始计)
int
main() {
#ifdef __SMALL__
freopen("A-small-practice.in", "r", stdin);
freopen("A-small-practice.out", "w", stdout);
#endif
#ifdef __LARGE__
freopen("A-large-practice.in", "r", stdin);
freopen("A-large-practice.out", "w", stdout);
#endif
int nscn, iscn;
int n;//矩阵的规模
int mov;//待移动的行的序号
int i, j;//计数变量
int ans;//最终结果,即行交换的最小次数
scanf("%d", &nscn);
iscn = 0;
while ( nscn-- ) {
scanf("%d", &n);
for ( i = 0; i < n; i++ ) scanf("%s", m[i]);
for ( i = 0; i < n; i++ ) {//找出每行最后一个1出现的位置
pos[i] = -1;
for ( j = 0; j < n; j++ )
if ( '1' == m[i][j] )
pos[i] = j;
}
//如果矩阵是按照规定布置的,则第i行最后一1出现的位置应该是i或者i - 1
//所以可以从i行开始向后扫描,找出里i行最近的满足上述条件的行逐个向上交换到i行即可
ans = 0;
for ( i = 0; i < n; i++ ) {//待处理的行i
mov = -1;//初始化,表示什么都没找到
for ( j = i; j < n; j++ )//往下检查,找出第一个符合要求的(即贪心选择)
if ( pos[j] <= i ) {
mov = j;//找到后立马跳出,进行交换
break;
}
if ( -1 == mov || i == mov ) continue;//如果没找到或者改行本来就已经符合要求了
//则直接跳过即可
for ( j = mov; j > i; j-- )//找到了,则逐行向上交换
//这里可以不必实际交换,可以用逐行向上覆盖的方法模拟交换
//以减少时间和空间的消耗
//由于接下来的搜索和之前的i无关,因此可以将第i行闲置,不做覆盖
pos[j] = pos[j - 1];
ans += mov - i;//累加交换次数
}
printf("Case #%d: %d\n", ++iscn, ans);
}
fclose(stdin);
fclose(stdout);
return 0;
}
无注释代码:
#include <stdio.h>
#define MAXN 40
char m[MAXN][MAXN];
char pos[MAXN];
int
main() {
#ifdef __SMALL__
freopen("A-small-practice.in", "r", stdin);
freopen("A-small-practice.out", "w", stdout);
#endif
#ifdef __LARGE__
freopen("A-large-practice.in", "r", stdin);
freopen("A-large-practice.out", "w", stdout);
#endif
int nscn, iscn;
int n;
int mov;
int i, j;
int ans;
scanf("%d", &nscn);
iscn = 0;
while ( nscn-- ) {
scanf("%d", &n);
for ( i = 0; i < n; i++ ) scanf("%s", m[i]);
for ( i = 0; i < n; i++ ) {
pos[i] = -1;
for ( j = 0; j < n; j++ )
if ( '1' == m[i][j] )
pos[i] = j;
}
ans = 0;
for ( i = 0; i < n; i++ ) {
mov = -1;
for ( j = i; j < n; j++ )
if ( pos[j] <= i ) {
mov = j;
break;
}
if ( -1 == mov || i == mov ) continue;
for ( j = mov; j > i; j-- )
pos[j] = pos[j - 1];
ans += mov - i;
}
printf("Case #%d: %d\n", ++iscn, ans);
}
fclose(stdin);
fclose(stdout);
return 0;
}
单词解释:
dashboard:n, 仪表盘,控制面板
column:n, 列,圆柱
keep track of:vt, 记录,与...保持联系