2015年国家集训队测试 矩阵变换

27 篇文章 0 订阅

居然给想出解法了。。。。

从题目中我们可以看出,每个数一定是尽量取列靠后的。

如果这样一行中出现了多个数怎么办?拿纸出来画一画可以发现我们因该保留靠前的那一个而把靠后的一个再向前一列取一下。

#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
#define pb push_back
int g[205],rk[205][205],q[200*200+5];
int Case,n,m,x,i,j,l,r,t;
struct arr
{
  int x,y;
  bool operator <(const arr &a)const
    { return y<a.y; }
} tmp;
vector <arr> num[205];

int read(){
  int ret=0;
  char ch=getchar();
  while (ch<'0' || ch>'9') ch=getchar();
  while (ch>='0' && ch<='9')
    {ret=ret*10+ch-'0'; ch=getchar();}
  return ret;
}

bool calc(){
  memset(g,0,sizeof(g));
  for (i=1;i<=n;i++)
    q[i] = i;
  for (l=1, r=n;l<=r;l++){
  	t = q[l];
  	while (!num[t].empty()){
  	  tmp = num[t].back();
  	  if (g[tmp.x]==0) {g[tmp.x]=t;break;}
  	  if (rk[ tmp.x ][ g[tmp.x] ]>tmp.y)
		{ q[++r]=g[tmp.x]; g[tmp.x]=t; break; }
	  num[t].pop_back();
    }
    if (num[t].empty()) break;
    num[t].pop_back();
  }
  return 1;
}

int main(){
  //freopen("3816.in","r",stdin);
  //freopen("3816.out","w",stdout);
  Case=read(); 
  //scanf("%d",&Case);
  while (Case--){
  	n=read(); m=read();
  	//scanf("%d%d",&n,&m);
  	for (i=1;i<=n;i++) num[i].clear();
  	for (i=1;i<=n;i++)
  	  for (j=1;j<=m;j++){
  	  	x=read();
  	  	//scanf("%d",&x);
  	  	if (x!=0){
		  num[x].pb( (arr){i,j} );
		  rk[i][x] = j;
	    }
  	  }
  	for (i=1;i<=n;i++)
  	  sort( num[i].begin(), num[i].end() );
  	if (!calc()) {puts("\(^o^)/");continue;}
  	for (i=1;i<n;i++) printf("%d ",g[i]);
  	printf("%d\n",g[n]);
  }
  return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值