题解:P13440 [GCJ 2009 #2] Crazy Rows
简述题意:存在一个正方形矩阵,每次操作交换相邻两行,最后要使得矩阵中的 \(1\) 全部处于主对角线上或它左边。
主对角线是矩阵左上角与右下角两顶点的连线。题干中也说了,只有 \(j \leq i\) 时,才有 \(a_{i,j}=1\) 可以成立。
那么,我们可以记录某一行最右边 \(1\) 的地址,从而那一行必不能处于所记录地址的上方。即若 \(a_{i,j}=1\) 则原来第 \(i\) 行最终处于第 \(j\) 行或其下方。
至此思路就清晰了。感觉实现起来有点像冒泡排序,把第一个可以放在第一排的放过来后就跳到后面,一直到最后一排,此过程中统计答案即可。
代码如下
#include<bits/stdc++.h>
#define ll long long
#define ri register int
using namespace std;
const int inf=0x3f3f3f3f;
const int N=44;
int T,n,f[N],ans;
char s[N];
signed main()
{
scanf("%d",&T);
for(ri qwq=1;qwq<=T;qwq++)
{
scanf("%d",&n);
memset(f,0,sizeof(f));
ans=0;//记得多测清空
for(ri i=1;i<=n;i++)
{
scanf("%s",s+1);//下标从1开始
for(ri j=n;j>=1;j--)
{
if(s[j]=='1')//从右往左遍历遇到的第一个'1'即为所求
{ //也算是小优化吧
f[i]=j;break;
}
}
}
for(ri i=1;i<=n;i++)
{
if(f[i]<=i)continue;//本身就满足
for(ri j=i+1;j<=n;j++)
{
if(f[j]<=i)
{
ans+=j-i;
for(ri k=j;k>i;k--)
{
swap(f[k],f[k-1]);
}
break;
}
}
}
printf("Case #%d: %d\n",qwq,ans);
}
return 0;
}
感谢阅读。
本文来自博客园,作者:Circle_Table,转载请注明原文链接:https://www.cnblogs.com/Circle-Table/articles/19177421

浙公网安备 33010602011771号