UVALive 3510 Pixel Shuffle

针对一个大小为n*n的图片,通过多种变换操作(如旋转、对称等),计算出一组变换组合使得图片恢复原状所需的最小执行次数。采用矩阵模拟变换过程,并利用数学方法求最小公倍数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://livearchive.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1511

题目描述:

假设有个大小为n*n的图片,然后有若干变换方式:不变、逆时针旋转、左右对称、只有上半部分左右对称、只有下半部分上下对称、把偶数行压到上半部分且把奇数行压到下半部分、混合。和这些变换的逆(比如逆时针旋转反过来就是顺时针旋转)。
现给出一组这些变换的组合,问这个组合最少要执行多少次才能使图片和原来一样。

输入,图片边长n,变换的组合。
输出,最小需要的次数。

解题思路:

构造一个矩阵并给每个点编号,把最开始的那组置换模拟一遍,便得出经过一组变换后每个点能到达哪里。然后从每个点搜经过多少次变换能到达原来的位置。然后求它们的最小共倍数即可。
题目本身不难,但模拟得真心烦,而且输入格式也很奇葩,那组变换要倒着来。而且gets AC、getline WA,这是为什么呢?

代码供参考:

#include<cstdio>
#include<sstream>
#include<cstring>
#include<string>
#include<iostream>
#include<stack>
using namespace std;
void get(int v,int &x,int &y,int n){
	x=v/n;y=v%n;
}
void id(int a[][1100],int res[][1100],int n){
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			res[i][j]=a[i][j];
		}
	}
}
void ret(int a[][1100],int res[][1100],int n){
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			int x,y;
			get(a[i][j],x,y,n);
			res[x][y]=i*n+j;
		}
	}
}
void rot(int a[][1100],int res[][1100],int n){
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			res[n-j-1][i]=a[i][j];
		}
	}
}
void rot_(int a[][1100],int res[][1100],int n){
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			res[i][j]=a[n-j-1][i];
		}
	}
}
void sym(int a[][1100],int res[][1100],int n){
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			res[i][j]=a[i][n-1-j];
		}
	}
}
void sym_(int a[][1100],int res[][1100],int n){
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			res[i][n-i-j]=a[i][j];
		}
	}
}
void bhsym(int a[][1100],int res[][1100],int n){
	for(int i=0;i<n/2;i++){
		for(int j=0;j<n;j++){
			res[i][j]=a[i][j];
		}
	}
	for(int i=n/2;i<n;i++){
		for(int j=0;j<n;j++){
			res[i][j]=a[i][n-1-j];
		}
	}
}
void bhsym_(int a[][1100],int res[][1100],int n){
	for(int i=0;i<n/2;i++){
		for(int j=0;j<n;j++){
			res[i][j]=a[i][j];
		}
	}
	for(int i=n/2;i<n;i++){
		for(int j=0;j<n;j++){
			res[i][n-1-j]=a[i][j];
		}
	}
}
void bvsym(int a[][1100],int res[][1100],int n){
	for(int i=0;i<n;i++){
		if(i<n/2)for(int j=0;j<n;j++)res[i][j]=a[i][j];
		else{
			for(int j=0;j<n;j++){
				res[i][j]=a[3*n/2-i-1][j];
			}
		}
	}
}
void bvsym_(int a[][1100],int res[][1100],int n){
	for(int i=0;i<n;i++){
		if(i<n/2)for(int j=0;j<n;j++)res[i][j]=a[i][j];
		else{
			for(int j=0;j<n;j++){
				res[3*n/2-i-1][j]=a[i][j];
			}
		}
	}
}
void div(int a[][1100],int res[][1100],int n){
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			if(i%2)res[i/2+n/2][j]=a[i][j];
			else res[i/2][j]=a[i][j];
		}
	}
}
void div_(int a[][1100],int res[][1100],int n){
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			if(i%2)res[i][j]=a[i/2+n/2][j];
			else res[i][j]=a[i/2][j];
		}
	}
}

void mix(int a[][1100],int res[][1100],int n){
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			if(i%2==0){
				if(j%2==0)res[i][j]=a[i][j/2];
				else res[i][j]=a[i+1][j/2];
			}else{
				if(j%2==0)res[i][j]=a[i-1][n/2+j/2];
				else res[i][j]=a[i][n/2+j/2];
			}
		}
	}
}
void mix_(int a[][1100],int res[][1100],int n){
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			if(i%2==0){
				if(j%2==0)res[i][j/2]=a[i][j];
				else res[i+1][j/2]=a[i][j];
			}else{
				if(j%2==0)res[i-1][n/2+j/2]=a[i][j];
				else res[i][n/2+j/2]=a[i][j];
			}
		}
	}
}
void print(int a[][1100],int n){
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			printf("%2d ",a[i][j]);
		}
		printf("\n");
	}
}
char str[300];
char s[20];
int a[1100][1100],res[1100][1100];
bool vis[1100][1100];
long long gcd(long long x,long long y){return y?gcd(y,x%y):x;}
int main(){
	//freopen("data.in","r",stdin);
	//freopen("data.out","w",stdout);
	int T,n;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);getchar();
		gets(str+1);
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				a[i][j]=i*n+j;
			}
		}
		str[0]=' ';
		int len=strlen(str+1);
		str[len+1]=' ';
		int o=0;
		int j;
		for(int i=len;i>=0;i--){
			if(str[i]==' '){
				for(j=i+1;str[j]!=' '&&str[j]!='-';j++)
					s[j-i-1]=str[j];
				s[j-i-1]='\0';
				if(strcmp(s,"id")==0){
					id(a,res,n);
				}else if(strcmp(s,"rot")==0){
					if(o==1){
						rot(a,res,n); id(res,a,n);
						rot(a,res,n); id(res,a,n);
					}
					rot(a,res,n);
					id(res,a,n);
				}else if(strcmp(s,"sym")==0){
					sym(a,res,n);id(res,a,n);
				} else if(strcmp(s,"bhsym")==0){
					bhsym(a,res,n);id(res,a,n);
				}else if(strcmp(s,"bvsym")==0){
					bvsym(a,res,n);id(res,a,n);
				}else if(strcmp(s,"div")==0){
					if(o==0){div(a,res,n);id(res,a,n);}
					else {div_(a,res,n);id(res,a,n);}
				}else if(strcmp(s,"mix")==0){
					if(o==0){mix(a,res,n);id(res,a,n);}
					else {mix_(a,res,n);id(res,a,n);}
				}
				o=0;
			}
			if(str[i]=='-')o=1;
		}
		long long mul=1;
		memset(vis,false,sizeof(vis));
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				long long len=0;
				if(vis[i][j])continue;
				else{
					int x=i,y=j;
					while(vis[x][y]==false){
						vis[x][y]=true;
						len++;
						get(a[x][y],x,y,n);
					}
					mul=mul*(len/gcd(mul,len));
				}
			}
		}
		printf("%lld\n",mul);
		if(T)printf("\n");

}

一个打表的代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
string a[14]={"id","id-","rot","rot-","sym","sym-","bhsym","bhsym-","bvsym","bvsym-","div","div-","mix","mix-"};
int main(){
	int T=100;
	freopen("data.in","w",stdout);
	printf("%d\n",T);
	for(int i=0;i<T;i++){
		if(i)cout<<endl;
		printf("1024\n");
		for(int j=0;j<5;j++){
			if(!j)cout<<a[rand()%14];
			else cout<<" "<<a[rand()%14];
		}
		cout<<endl;
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值