Google Code Jam 2009 Round2 A (脑洞题)

来源:互联网 发布:淘宝卖家旺旺号 编辑:程序博客网 时间:2024/05/21 08:53

Problem A. Crazy Rows

This contest is open for practice. You can try every problem as many times as you like, though we won't keep track of which problems you solve. Read theQuick-Start Guide to get started.
Small input
6 points 
 Large input
10 points 
Judge's response for last submission: Correct.

Problem

You are given an N x N matrix with 0 and 1 values. You can swap any twoadjacent rows of the matrix.

Your goal is to have all the 1 values in the matrix below or on the main diagonal. That is, for each X where 1 ≤ X ≤ N, there must be no 1 values in row X that are to the right of column X.

Return the minimum number of row swaps you need to achieve the goal.

Input

The first line of input gives the number of cases, T. T test cases follow.
The first line of each test case has one integer, N. Each of the nextN lines containsN characters. Each character is either 0 or 1.

Output

For each test case, output

Case #X: K
where X is the test case number, starting from 1, and K is the minimum number of row swaps needed to have all the 1 values in the matrix below or on the main diagonal.

You are guaranteed that there is a solution for each test case.

Limits

1 ≤ T ≤ 60

Small dataset

1 ≤ N ≤ 8

Large dataset

1 ≤ N ≤ 40

Sample


Input
 
Output
 3
2
10
11
3
001
100
010
4
1110
1100
1100
1000
Case #1: 0
Case #2: 2
Case #3: 4


题目大意:

    输入一个N*N的只有0和1的矩阵,每次可以交换相邻的两行,求把矩阵转化成主对角线上方的元素都是0最小的交换次数。


解题思路:

    首先,对于矩阵的每一行我们只关心最右边的1的位置,所以需要先预处理出每一行最右边一行的1的位置。

    由于每次只能交换相邻的两行,所以要想步数最少定是用类似于冒泡排序的方法。先通过交换确定最上面一行(先确定最下面一行也可以),再确定第二行,再第三行……

    对于每一行的确定,我们只要从这一行往下寻找第一个移动到这里后不会超过对角线的行就可以保证步数最小。


附Correct代码:

#include <iostream>#include <algorithm>#include <cstring>#include <cstdio>using namespace std;//#define LOCAL_TESTconst int maxn=40+3;int N;char land[maxn][maxn];//矩阵int a[maxn];//每一行最后一个1出现的位置int main(){#ifndef LOCAL_TEST    freopen("/Users/xuehao/Downloads/A-large-practice.in","r",stdin);    freopen("/Users/xuehao/Documents/s1/s1/out","w",stdout);#endif    int T;    scanf("%d",&T);    for(int tt=1;tt<=T;++tt)    {        int ans=0;        scanf("%d",&N);        for(int i=0;i<N;++i)        {            scanf("%s",land[i]);            a[i]=-1;//如果没有1,则令最后一个1的位置为-1            for(int j=0;j<N;++j)                if(land[i][j]=='1')                    a[i]=j;        }        for(int i=0;i<N;++i)        {            int pos=-1;            for(int j=i;j<N;++j)                if(a[j]<=i)//第一个1不超过位置i的对角线的行                {                    pos=j;                    break;                }            for(int j=pos;j>i;--j)//交换            {                swap(a[j],a[j-1]);                ++ans;            }        }        printf("Case #%d: %d\n",tt,ans);    }    #ifndef LOCAL_TEST    fclose(stdin);    fclose(stdout);#endif        return 0;}


0 0