题目链接: http://codeforces.com/contest/724/problem/B
思路: 先把一步能够到达有序的情况枚举存在一个二维数组a里面。然后输入每一行 对每一行进行两两交换,交换后把对应的 a数组的状态加一。最后看是否存在到达n的状态。
#include<cstdio> #include<cstring> #include<cctype> #include<cmath> #include<set> #include<map> #include<list> #include<queue> #include<deque> #include<stack> #include<string> #include<vector> #include<iostream> #include<algorithm> #include<stdlib.h> #include<time.h> using namespace std; typedef long long LL; const int INF=2e9+1e8; const int MOD=1e9+7; const int MAXSIZE=1e6+5; const double eps=0.0000000001; void fre() { freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); } #define memst(a,b) memset(a,b,sizeof(a)) #define fr(i,a,n) for(int i=a;i<n;i++) int n,m,dp[405][21],tot; int temp[22],ans[405]; void init() { tot=0; memst(ans,0); for(int i=0; i<m; i++) { temp[i]=i+1; dp[tot][i]=i+1; } tot++; for(int i=0; i<m-1; i++) for(int j=i+1; j<m; j++) { for(int k=0; k<m; k++) { if(k==i) dp[tot][j]=temp[k]; else if(k==j) dp[tot][i]=temp[k]; else dp[tot][k]=temp[k]; } tot++; } return ; } bool cmp(int pos,int *a) { for(int i=0;i<m;i++) if(dp[pos][i]!=a[i]) return false; return true; } void bian(int *a) { for(int i=0;i<tot;i++) { if(cmp(i,a)) ans[i]++; } } void add() { int a[30]; for(int i=0;i<m;i++) a[i]=temp[i]; bian(a); for(int i=0; i<m-1; i++) for(int j=i+1; j<m; j++) { for(int k=0; k<m; k++) { if(k==i) a[j]=temp[k]; else if(k==j) a[i]=temp[k]; else a[k]=temp[k]; } bian(a); } } bool get() { for(int i=0;i<tot;i++) if(ans[i]==n) return true; return false; } int main() { scanf("%d%d",&n,&m); init(); for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { scanf("%d",&temp[j]); } add(); } if(get()) printf("YES "); else printf("NO "); return 0; } // 复杂度 1e6 多一点
另一个写法请参考 这个 。这个方法更容易理解。
-----------------------------------------------------------------------分割线---------------------------------------------------------------------------------------------------------------------
下面是 C 题 : http://codeforces.com/problemset/problem/722/C
有两篇文章,目前看了模拟这个想法,写了 模拟 的,做法二是 扩展欧几里得 + 计算几何。
模拟思路,预处理到边上的点的步数,对于一个点,往四个方向找,取最小值就可以了。
#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include <string> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <sstream> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; const int MAX=100005; typedef long long int LL; int a[MAX],b[MAX]; LL vis[MAX][4][4]; int n,m,k; void init() { memset(vis,-1,sizeof(vis)); int tmp=0; int x=0,y=0; LL ti=0; while(1) { if(tmp==0) { if((n-x)+y==m) break; if((n-x)+y<m) vis[(n-x)+y][3][0]=ti+n-x,ti=ti+n-x,y=(n-x)+y,x=n,tmp=3; else vis[x+(m-y)][2][0]=ti+m-y,ti=ti+m-y,x=x+(m-y),y=m,tmp=1; } else if(tmp==1) { if(y-(n-x)==0) break; if(y>n-x) vis[y-(n-x)][3][1]=ti+(n-x),ti=ti+(n-x),y=y-(n-x),x=n,tmp=2; else vis[x+y][0][1]=ti+y,ti=ti+y,x=x+y,y=0,tmp=0; } else if(tmp==2) { if(x==y) break; if(x<y) vis[y-x][1][2]=ti+x,ti=ti+x,y=y-x,x=0,tmp=1; else vis[x-y][0][2]=ti+y,ti=ti+y,x=x-y,y=0,tmp=3; } else if(tmp==3) { if(y+x==m) break; if(y+x<m) vis[y+x][1][3]=ti+x,ti=ti+x,y=y+x,x=0,tmp=0; else vis[x-(m-y)][2][3]=ti+(m-y),ti=ti+(m-y),x=x-(m-y),y=m,tmp=2; } } return ; } int main() { while(cin>>n>>m>>k) { for(int i=0; i<k; i++) { scanf("%d%d",&a[i],&b[i]); } init(); for(int i=0; i<k; i++) { LL ans=1e18; if(a[i]==b[i]) { printf("%d ",a[i]); continue; } if((n-a[i])+b[i]>m) { if(vis[a[i]+(m-b[i])][2][3]!=-1) { ans=min(ans,vis[a[i]+(m-b[i])][2][3]+m-b[i]); } } if((n-a[i])+b[i]<m) { if(vis[b[i]+n-a[i]][3][1]!=-1) { ans=min(ans,vis[b[i]+n-a[i]][3][1]+n-a[i]); } } if(b[i]>n-a[i]) { if(vis[b[i]-(n-a[i])][3][0]!=-1) { ans=min(ans,vis[b[i]-(n-a[i])][3][0]+n-a[i]); } } if(b[i]<n-a[i]) { if(vis[a[i]+b[i]][0][2]!=-1) { ans=min(ans,vis[a[i]+b[i]][0][2]+b[i]); } } if(a[i]<b[i]) { if(vis[b[i]-a[i]][1][3]!=-1) { ans=min(ans,vis[b[i]-a[i]][1][3]+a[i]); } } if(a[i]>b[i]) { if(vis[a[i]-b[i]][0][1]!=-1) { ans=min(ans,vis[a[i]-b[i]][0][1]+b[i]); } } if(a[i]+b[i]>m) { if(vis[a[i]-(m-b[i])][2][0]!=-1) { ans=min(ans,vis[a[i]-(m-b[i])][2][0]+(m-b[i])); } } if(a[i]+b[i]<m) { if(vis[a[i]+b[i]][1][2]!=-1) { ans=min(ans,vis[a[i]+b[i]][1][2]+a[i]); } } if(ans!=1e18) printf("%I64d ",ans); else printf("-1 "); } } return 0; }