InterviewStreet题目(2)


题目描述:

 

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:

  • M(B) = min( B1 Xor B2, B2 Xor B3, B3 Xor B4, ... , Bn-1 Xor Bn, Bn Xor B1 ) is not less than 2^K.

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 m=new ArrayList();
		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			{
				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;
	}
}

你可能感兴趣的:(算法与数学)