题解: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;
}

感谢阅读。

posted @ 2025-10-30 16:15  Circle_Table  阅读(5)  评论(0)    收藏  举报