zoukankan      html  css  js  c++  java
  • 2009 Round2 A Crazy Rows (模拟)

    Problem

    You are given an N x N matrix with 0 and 1 values. You can swap any two adjacent 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 next N lines contains Ncharacters. 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

    分析:
    所以我们先暂时考虑: 最后应该把哪一行交换到第一行,第一行应该为全0行或首元素为1其他为0的行 ,而这一行可以交换到任意一行,当有多个满足条件的行时选择离第一行近的行对应的最终费用小 ,因为只能交换相邻的两行
    假设:X1 X2 X3……Xn 其中X1的元素不应该在第一个位置
    而这n个元素只有 X2 X3的元素 可以在X1的位置
    那么若交换 X2 X1则需要一步 然后X3又和X1交换 共两步 得到 X2 X3 X1……
    若把X3交换到第一行 两步 X2再与X1交换一步 共三步 得到 X3 X2 X1……
    这两种情况来看 第二种可以看作是第一种移动完了之后 又交换了 X2 X3
    如果X1 X2 X3之间出现了多个不应该在第一个的元素 是一样的道理
    你可能会想 在X1 X2 X3之间插入的元素 万一出现也适合第一个位置的怎么办
    其实上述的X1 X2 X3 是有条件的筛选的 每两个之间没有可以当第一个位置的元素
    如果有 比如 X1 Xm X2 X3中 Xm也符合第一个位置
    那么 此时应该把 X1 Xm X2 分别当作上述情况的 X1 X2 X3 她们只是代号而已
    这个地方懂了 也就明白 为什么当有多个满足条件的行时选择离第一行近的行交换 则对应的最终费用小了。

    代码:

    #include<iostream>
    #include<stdio.h>
    using namespace std;
    int M[100][100];///保存矩阵的形式
    int a[100];///用来存某一行的最后一个1在第几列
    int n;
    
    void solve()
    {
        int ans=0;
        for(int i=0; i<n; i++)
        {
            a[i]=-1;
            for(int j=0; j<n; j++)
            {
                if(M[i][j]==1) a[i]=j;///存下第i行的最后一个1在第j列
            }
        }
    
        for(int i=0; i<n; i++)
        {
            int pos=-1;
            for(int j=i; j<n; j++)///每次的前面的行都是已经排好的,只需要往后面找就行了
            {
                if(a[j]<=i)
                {
                    pos=j;///看下在第几行
                    break;
                }
            }
    
            for(int j=pos; j>i; j--)///然后依次一行一行的交换上去
            {
                swap(a[j],a[j-1]);
                ans++;
            }
        }
        printf("%d
    ",ans);
    }
    
    
    int main()
    {
        while(~scanf("%d",&n))
        {
            for(int i=0; i<n; i++)
                for(int j=0; j<n; j++)
                    scanf("%d",&M[i][j]);
            solve();
        }
        return 0;
    }
    
  • 相关阅读:
    645. 错误的集合
    88. 合并两个有序数组
    125. 验证回文串
    常用的浏览器
    网页的相关概念
    HTML简介
    商城搜索解决方案
    用VirtualBox安装Centos7
    Eureka自我保护机制
    服务发现Discovery(查看运行的服务)
  • 原文地址:https://www.cnblogs.com/cmmdc/p/7204326.html
Copyright © 2011-2022 走看看