topcoder srm 360 div1

problem1 link

(1)$n \neq m$时,假设$n<m$,那么同一行中的$m$个数字必定都相等。

(2)$n=m$时,要满足任意的$i_{1},i_{2},j_{1},j_{2},A[i_{1}][j_{1}]+A[i_{2}][j_{2}]=A[i_{1}][j_{2}]+A[i_{2}][j_{1}]$

import java.util.*;
import java.math.*;
import static java.lang.Math.*;

public class SumOfSelectedCells {
	
	public String hypothesis(String[] table) {
		final String YES="CORRECT";
		final String NO="INCORRECT";
		final int n=table.length;
		int m=-1;
		int[][] g=new int[22][22];
		for(int i=0;i<n;++i) {
			String[] t=table[i].split("\\W+");
			if(m==-1) {
				m=t.length;
			}
			else {
				assert m==t.length;
			}
			for(int j=0;j<m;++j) {
				g[i][j]=Integer.valueOf(t[j]);
			}
		}
		if(n!=m) {
			if(n<m) {
				for(int i=0;i<n;++i) {
					for(int j=1;j<m;++j) {
						if(g[i][0]!=g[i][j]) {
							return NO;
						}
					}
				}
			}
			else {
				for(int j=0;j<m;++j) {
					for(int i=1;i<n;++i) {
						if(g[0][j]!=g[i][j]) {
							return NO;
						}
					}
				}
			}
		}
		else {
			for(int i1=0;i1<n;++i1) {
				for(int i2=i1+1;i2<n;++i2) {
					for(int j1=0;j1<m;++j1) {
						for(int j2=j1+1;j2<m;++j2) {
							if(g[i1][j1]+g[i2][j2]!=g[i1][j2]+g[i2][j1]) {
								return NO;
							}
						}
					}
				}
			}
		}
		return YES;
	}
}

  

problem2 link

仅当相邻时无解。有解时答案最大为4.因为可以将其中的一个围住。那么只需要检测小于4时是否可以。这时,可以暴力枚举然后判断连通性。

import java.util.*;
import java.math.*;
import static java.lang.Math.*;

public class PrinceOfPersia {

	static class pair {
		public int first;
		public int second;

		public pair() {}
		public pair(int first,int second) {
			this.first=first;
			this.second=second;
		}
	}

	int[][] visit=null;
	int index=0;
	int sx=-1,sy=-1,ex=-1,ey=-1;

	String[] maze=null;

	final int[] dx={0,0,1,-1};
	final int[] dy={1,-1,0,0};
	int n,m;

	List<pair> empty=null;

	boolean dfs(int x,int y) {
		if(x==ex&&y==ey) {
			return true;
		}
		if(x<0||x>=n||y<0||y>=m||maze[x].charAt(y)=='#') {
			return false;
		}
		if(index==visit[x][y]) {
			return false;
		}
		visit[x][y]=index;
		for(int i=0;i<4;++i) {
			if(dfs(x+dx[i],y+dy[i])) {
				return true;
			}
		}
		return false;
	}


	int cal() {
		++index;
		if(!dfs(sx,sy)) {
			return 0;
		}
		for(int i=0;i<empty.size();++i) {
			++index;
			visit[empty.get(i).first][empty.get(i).second]=index;
			if(!dfs(sx,sy)) {
				return 1;
			}
		}

		for(int i=0;i<empty.size();++i) {
			for(int j=i+1;j<empty.size();++j) {
				++index;
				visit[empty.get(i).first][empty.get(i).second]=index;
				visit[empty.get(j).first][empty.get(j).second]=index;
				if(!dfs(sx,sy)) {
					return 2;
				}
			}
		}

		for(int i=0;i<empty.size();++i) {
			for(int j=i+1;j<empty.size();++j) {
				for(int k=j+1;k<empty.size();++k) {
					++index;
					visit[empty.get(i).first][empty.get(i).second]=index;
					visit[empty.get(j).first][empty.get(j).second]=index;
					visit[empty.get(k).first][empty.get(k).second]=index;
					if(!dfs(sx,sy)) {
						return 3;
					}
				}
			}
		}
		return 4;
	}
	
	public int minObstacles(String[] maze) {

		this.maze=maze;
		n=maze.length;
		m=maze[0].length();
		visit=new int[n][m];
		empty=new ArrayList<>();
		for(int i=0;i<n;++i){
			for(int j=0;j<m;++j) {
				if(maze[i].charAt(j)=='P') {
					if(sx==-1) {
						sx=i;
						sy=j;
					}
					else {
						ex=i;
						ey=j;
					}
				}
				else if(maze[i].charAt(j)=='.') {
					empty.add(new pair(i,j));
				}
			}
		}
		if(sx==ex&&Math.abs(sy-ey)==1||sy==ey&&Math.abs(sx-ex)==1) {
			return -1;
		}
		return cal();
	}
}

  

problem3 link

设$m$ 为给出的数字个数.对于一个凸包,假设顶点大于3,那么去掉任意一个顶点后仍是凸包。所以:

(1)$m\geq 6$时,若为奇数只需要添加一个数字(这时可以暴力),为偶数不需要添加;

(2)$m<6$时,需要添加$6-m$个数字。$m=2,3,4,5$时可以暴力;$m=0$时答案为$1,1,1,2,2,1$,$m=1$时,若给出的数字为1则答案为$1,1,2,2,1$,否则答案为$1,1,1,1,2$

那么,剩下的问题就是判断凸包,只需判断:(1)任意三个点角度小于180;(2)任意两条边不相交(这个只需要判断$y$连续严格增大的顶点段的个数以及$y$严格减小的连续顶点段的个数,为凸包时这些段数最大为3)

import java.util.*;
import java.math.*;
import static java.lang.Math.*;

public class ConvexArray {

	static class point {
		public long x;
		public long y;

		public point() {}
		public point(long x,long y) {
			this.x=x;
			this.y=y;
		}
		public point add(point a) {
			return new point(x+a.x,y+a.y);
		}
		public point substract(point a) {
			return new point(x-a.x,y-a.y);
		}
		public long crossMultiply(point a) {
			return x*a.y-y*a.x;
		}

	}

	boolean check(List<Integer> list) {
		final int n=list.size()>>1;
		List<point> g=new ArrayList<>();
		for(int i=0;i<n;++i) {
			g.add(new point(list.get(i<<1),list.get(i<<1|1)));
		}
		long a=0;
		for(int i=0;i<n;++i) {
			a+=g.get(i).crossMultiply(g.get((i+1)%n));
		}
		if(a==0) {
			return false;
		}
		if(a<0) {
			int ll=0,rr=n-1;
			while(ll<rr) {
				point p=g.get(ll);
				point q=g.get(rr);
				g.set(ll,q);
				g.set(rr,p);
				++ll;
				--rr;
			}
		}
		for(int i=0;i<n;++i) {
			point p=g.get(i);
			point q=g.get((i+1)%n);
			point r=g.get((i+2)%n);
			if(q.substract(p).crossMultiply(r.substract(p))<=0) {
				return false;
			}
		}
		int num=0;
		for(int i=0;i<n;) {
			if(g.get(i).y<g.get((i+1)%n).y) {
				++num;
				while(g.get(i).y<g.get((i+1)%n).y) {
					++i;
					if(i==n) {
						break;
					}
				}
			}
			else if(g.get(i).y>g.get((i+1)%n).y) {
				++num;
				while(g.get(i).y>g.get((i+1)%n).y) {
					++i;
					if(i==n) {
						break;
					}
				}
			}
			else {
				++i;
			}
		}
		if(num>3) {
			return false;
		}
		return true;
	}
	
	public int[] getEnding(int[] beginning) {
		final int n=beginning.length;
		if(n>=6) {
			List<Integer> list=new ArrayList<>();
			for(int i=0;i<n;++i) {
				list.add(beginning[i]);
			}
			if(n%2==1) {
				list.add(0);
				for(int i=1;i<=50;++i){
					list.set(list.size()-1,i);
					if(check(list)) {
						return new int[]{i};
					}
				}
				return new int[]{-1};
			}
			else {
				if(check(list)) {
					return new int[0];
				}
				else {
					return new int[]{-1};
				}
			}
		}
		if(n==0) {
			return new int[]{1,1,1,2,2,1};
		}
		if(n==1) {
			final int x=beginning[0];
			if(x==1) {
				return new int[]{1,1,2,2,1};
			}
			return new int[]{1,1,1,1,2};
		}
		List<Integer> list=new ArrayList<>();
		for(int i=0;i<n;++i) {
			list.add(beginning[i]);
		}
		while(list.size()<6) {
			list.add(0);
		}
		if(dfs(n,list)) {
			int[] result=new int[6-n];
			for(int i=n;i<6;++i) {
				result[i-n]=list.get(i);
			}
			return result;
		}
		return new int[]{-1};
	}

	boolean dfs(int t,List<Integer> list) {
		if(t==6) {
			return check(list);
		}
		for(int i=1;i<=50;++i) {
			list.set(t,i);
			if(dfs(t+1,list)) {
				return true;
			}
		}
		return false;
	}
}

  

posted @ 2017-09-11 20:37  朝拜明天19891101  阅读(201)  评论(0编辑  收藏  举报