topcoder srm 340 div1

problem1 link 

$f[i][L][R]$表示计算到第$i$个,最小最大值是$L,R$时的最少个数。

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

public class ProblemsToSolve {


	int[] unique(int[] p) {
		int n=p.length;
		int[] a=new int[n];
		for(int i=0;i<n;++i) {
			a[i]=p[i];
		}
		Arrays.sort(a);
		int id=0;
		for(int i=1;i<n;++i) {
			if(a[i]!=a[id]) {
				a[++id]=a[i];
			}
		}
		++id;
		if(id==n) {
			return a;
		}
		int[] q=new int[id];
		for(int i=0;i<id;++i) {
			q[i]=a[i];
		}
		return q;
	}

	int getindex(int[] p,int x) {
		for(int i=0;i<p.length;++i) {
			if(p[i]==x) {
				return i;
			}
		}
		return -1;
	}

	public int minNumber(int[] p,int variety) {
		final int n=p.length;
		final int[] a=unique(p);
		final int m=a.length;
		int[][][] f=new int[n][m][m];

		for(int i=0;i<n;++i) {
			p[i]=getindex(a,p[i]);
		}

		int result=n;
		for(int i=0;i<n;++i) {
			for(int j=0;j<m;++j) {
				for(int k=0;k<m;++k) {
					f[i][j][k]=-1;
				}
			}
		}
		f[0][p[0]][p[0]]=1;
		for(int i=1;i<n;++i) {
			for(int j=i-1;j>=i-2&&j>=0;--j) {
				for(int x=0;x<m;++x) {
					for(int y=x;y<m;++y) {
						if(f[j][x][y]==-1) continue;

						if(p[i]>y) {
							if(a[p[i]]-a[x]>=variety) {
								result=Math.min(result,f[j][x][y]+1);
								continue;
							}
						}
						else if(p[i]<x) {
							if(a[y]-a[p[i]]>=variety) {
								result=Math.min(result,f[j][x][y]+1);
								continue;
							}
						}

						final int nx=Math.min(x,p[i]);
						final int ny=Math.max(y,p[i]);

						if(f[i][nx][ny]==-1||f[i][nx][ny]>f[j][x][y]+1) {
							f[i][nx][ny]=f[j][x][y]+1;
						}

					}
				}
			}
		}
		return result;
	}
}

problem2 link

$f[i][j]$表示两个分数分别达到$i,j$时选择的最少课程数,并记录选择的课程是哪些。这样进行bfs即可。

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

public class CsCourses {


	String int2string(int x) {
		if(x<10) {
			return "0"+Integer.toString(x);
		}
		return Integer.toString(x);
	}

	public int[] getOrder(int[] t, int[] p, int[] e, int skillBound) {
		if(skillBound==0) {
			return new int[0];
		}
		final int n=t.length;

		int[][] f=new int[51][51];
		String[][] d=new String[51][];
		boolean[][] inq=new boolean[51][51];
		for(int i=0;i<51;++i) {
			d[i]=new String[51];
			for(int j=0;j<51;++j) {
				f[i][j]=-1;
				inq[i][j]=false;
			}
		}

		Queue<Integer> que=new LinkedList<>();


		for(int i=0;i<n;++i) {
			if(t[i]<=1&&p[i]<=1&&e[i]>=1&&t[i]+p[i]>0&&f[t[i]][p[i]]==-1) {
				f[t[i]][p[i]]=1;
				d[t[i]][p[i]]=int2string(i);
				que.offer(t[i]*100+p[i]);
				inq[t[i]][p[i]]=true;
			}
		}


		while(!que.isEmpty()) {
			final int ii=que.peek()/100;
			final int jj=que.peek()%100;
			que.poll();
			if(ii>=skillBound&&jj>=skillBound) {
				continue;
			}

			for(int k=0;k<n;++k) {
				if(t[k]<=ii&&p[k]<=jj) continue;
				if(t[k]-ii>1) continue;
				if(p[k]-jj>1) continue;
				if(e[k]<=f[ii][jj]) continue;
				final int nii=Math.max(ii,t[k]);
				final int njj=Math.max(jj,p[k]);

				if(f[nii][njj]==-1
						||f[nii][njj]>f[ii][jj]+1
						||f[nii][njj]==f[ii][jj]+1
						&&0<d[nii][njj].compareTo(d[ii][jj]+","+int2string(k))) {
					f[nii][njj]=f[ii][jj]+1;
					d[nii][njj]=d[ii][jj]+","+int2string(k);
					if(!inq[nii][njj]) {
						que.offer(nii*100+njj);
						inq[nii][njj]=true;
					}
				}

			}
		}
		int num=Integer.MAX_VALUE;
		String route="";
		for(int i=skillBound;i<51;++i) {
			for(int j=skillBound;j<51;++j) {
				if(f[i][j]!=-1&&f[i][j]<num||f[i][j]==num&&d[i][j].compareTo(route)<0) {
					num=f[i][j];
					route=d[i][j];
				}
			}
		}
		if(num==Integer.MAX_VALUE) {
			return new int[0];
		}
		String[] path=route.split(",");
		int[] result=new int[path.length];

		for(int i=0;i<path.length;++i) {
			result[i]=Integer.valueOf(path[i]);
		}
		return result;

	}
}

problem3 link

判断一个点在多边形的内部还是外部可以用射线法。一条从某一点发出的射线与多边形有奇数个交点则在内部。

初始时认为每个格子有个垂直向上的射线。每次横着走时,下面的所有格子与多边形的交点个数增加了1.

$f[x][y][mask]$表示从$(0,0)$走到$(x,y)$,经过的$'I'$或者$'X'$的状态是$mask$的最短路。

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

public class VegetableGarden {
	
	public int[] getMinDistances(String[] g) {
		final int n = g.length;
		final int m = g[0].length();
		int id = 0;
		int badMask=0;
		int iNum=0;
		List<Integer> list=new ArrayList<>();
		for(int i=0;i<n;++i) {
			for(int j=0;j<m;++j) {
				if(g[i].charAt(j)!='.') {
					if(g[i].charAt(j)=='X') {
						badMask|=1<<id;
					}
					else {
						++iNum;
					}
					list.add(i*100+j);
					++id;
				}
			}
		}
		int[][][] f=new int[n+1][m+1][1<<id];
		boolean[][][] inq=new boolean[n+1][m+1][1<<id];
		for(int i=0;i<n+1;++i) {
			for(int j=0;j<m+1;++j) {
				for(int k=0;k<(1<<id);++k) {
					f[i][j][k]=-1;
					inq[i][j][k]=false;
				}
			}
		}
		Queue<Integer> queue=new LinkedList<>();
		f[0][0][0]=0;
		inq[0][0][0]=true;
		queue.offer(0);
		final int[] dx={0,1,0,-1};
		final int[] dy={1,0,-1,0};
		while(!queue.isEmpty()) {
			final int mask=queue.peek()/10000;
			final int x=queue.peek()%10000/100;
			final int y=queue.peek()%100;
			queue.poll();
			inq[x][y][mask]=false;
			for(int d=0;d<4;++d) {
				final int xx=x+dx[d];
				final int yy=y+dy[d];
				if(xx<0||yy<0||xx>=n+1||yy>=m+1) continue;
				int nMask=mask;
				if(d==0||d==2) {
					final int column=d==0?y:y-1;

					for(int k=0;k<list.size();++k) {
						final int nx=list.get(k)/100;
						final int ny=list.get(k)%100;
						if(ny==column&&nx>=x) {
							nMask^=1<<k;
						}
					}
				}

				if(f[xx][yy][nMask]==-1||f[xx][yy][nMask]>f[x][y][mask]+1) {
					f[xx][yy][nMask]=f[x][y][mask]+1;
					if(!inq[xx][yy][nMask]) {
						inq[xx][yy][nMask]=true;
						queue.offer(nMask*10000+xx*100+yy);
					}
				}

			}
		}
		int[] result=new int[iNum];
		for(int i=0;i<(1<<id);++i) {
			if((i&badMask)!=0) continue;
			if(f[0][0][i]==-1) continue;
			int c=0;
			int k=i;
			while(k!=0) {
				c+=k&1;
				k>>=1;
			}
			if(c==0) {
				continue;
			}
			if(result[c-1]==0||result[c-1]>f[0][0][i]) {
				result[c-1]=f[0][0][i];
			}
		}
		return result;
	}
}

  

posted @ 2017-08-21 22:42  朝拜明天19891101  阅读(284)  评论(0编辑  收藏  举报