题目描述:
Suppose that A is a list of n numbers ( A1, A2, A3, ... , An) and B ( B1, B2, B3, .. ,Bn ) is a permutation of these numbers. We say B is K-Manipulative if and only if its following value:
You are given n number A1 to An, You have to find the biggest K such that there exists a permutation B of these numbers which is K-Manipulative.
Input:
In the first line of the input there is an integer N.
In the second line of input there are N integers A1 to An
N is not more than 100.
Ai is non-negative and will fit in 32-bit integer.
Output:
Print an integer to the output being the answer to the test. If there is no such K print -1 to the output.
题目分类:位操作
对于N个数,每一种排列对应一个K,同时每种排列可以看作是一种N*N的棋盘上非攻击型车的放置。
对于N个数中每两个数,其异或都会产生一个值,因此显而易见,K的值不会小于所有数中两个异或的最小值。
因此,算法的思路就是,构造N*N的棋盘,不断的剔除其中的最小值,直到再也不能摆上一种非攻击型车为止,此时最后剔除的最小值即为所求。
非攻击型车的摆放实际上就是一个二分图匹配,N*N的棋盘的行和列分别对应二分图的左部和右部,若此点可以摆一个车,就将相应的点连起来。
求二分图的最大匹配可以用最大流或者匈牙利算法,但因为每次剔除之后要做判断,使用匈牙利算法不用再做一次匹配,只需要重新寻找增广路径即可,时间复杂度较为优秀(也是我能想出的唯一不超时的方法)。
综合所述算法大致如下:
1、读入数字O(n)
2、计算矩阵中的值O(n*n)。
3、为了计算最小值因此进行排序O(n*n*logn)。
4、进行一次最大匹配,使用匈牙利算法,因为是完全图所以O(n*n*n)。
5、不断提出最小值,重新搜索增广路径,直到不能产生完全匹配,最多剔除n*n条路径,每次搜索增广路径耗时n*n,因此总的时间复杂度是O(n^4)
考虑到n的最大值是100,n的四次方大概是10^8,满足计算需求,因此算法合理。
提交通过!
代码如下:
import java.util.*; import java.io.*; public class Solution { private static int[][] m2; private static int[] useif; private static int[] link; private static int N; public static void main(String[] argvs) throws NumberFormatException, IOException { BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); N=Integer.valueOf(br.readLine()); String[] strs=br.readLine().split(" "); int[] nums=new int[N]; for(int i=0;i<=N-1;i++) { nums[i]=Integer.valueOf(strs[i]); } ArrayList<model> m=new ArrayList<model>(); m2=new int[N][N]; useif=new int[N]; link=new int[N]; for(int i=0;i<=N-1;i++) { link[i]=-1; for(int j=0;j<=N-1;j++) { m2[i][j]=1; } } for(int i=0;i<=N-1;i++) { for(int j=i;j<=N-1;j++) { m.add(new model(i,j,nums[i]^nums[j])); if(i!=j) { m.add(new model(j,i,nums[i]^nums[j])); } } } Collections.sort(m,new myComp()); MaxMatch(); for(int i=0;i<=m.size()-1;i++) { model mo=m.get(i); m2[mo.x][mo.y]=0; if(link[mo.y]==mo.x) { link[mo.y]=-1; for(int j=0;j<=N-1;j++) { useif[j]=0; } if(can(mo.x)==0) { int v=mo.value; int result=0; while(true) { v=v>>1; if(v==0) { System.out.println(result); return; } result++; } } } } } private static class model { int x; int y; int value; public model(int a,int b,int c) { x=a; y=b; value=c; } } private static class myComp implements Comparator { @Override public int compare(Object o1, Object o2) { model a1=(model)o1; model a2=(model)o2; if(a1.value<a2.value) { return -1; } if(a1.value==a2.value) { return 0; } return 1; } } private static int can(int t) { int i; for(i=0;i<=N-1;i++) { if(useif[i]==0 && m2[t][i]==1) { useif[i]=1; if(link[i]==-1 || can(link[i])==1) { link[i]=t; return 1; } } } return 0; } private static int MaxMatch() { int i,num; num=0; for(i=0;i<=N-1;i++) { for(int j=0;j<=N-1;j++) { useif[j]=0; } if(can(i)==1) num++; } return num; } }