题目链接: 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\n");
else printf("NO\n");
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\n",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\n",ans);
else printf("-1\n");
}
}
return 0;
}