topcoder srm 480 div1

problem1 link

直接模拟即可。

problem2 link

首先,网关一定是安装在client与server之间的链路上。而不会安装在client与client之间的链路上。对于一条路径c1->c2->c3->c4->s,且不存在任何一个其他的client使得c4到该client存在链路且该client可以到达s。假设c1->c2之间的链路安装了,那么c4->s之间的链路还要安装。所以只需要在c4->s之间的链路安装即可。

所以所有的安装位置一定是在client与server之间的链路上。且对于某个安装的链路c->s不存在其他的$c^{'}$使得c->$c^{'}$存在链路且$c^{'}$可以到达s。

problem3 link

每一段解码选择的区间为[L,R],那么设[L,R-1]之间的数字为num,R位置的字符为letter。这个可以表示为二元组{num,letter}。这里L位置的字符一定不能是0,所以num一定大于0.

对于连续的两段解码区间$[L_{1},R_{1}],[L_{2},R_{2}](R_{1}+1=L_{2})$,必须满足$R_{1} \ne R_{2}$

对于某一段{num,letter},假设是{6,3},第一次解码之后是333333。那么第二次解码有可能是一下几种情况:

(1)当前段所有数字,即333333作为后面一段数字的num出现,比如假设后面是两个4,即33333344,那么下一次解码可能是$\underset{3333334}{\underbrace{44........44}}$

(2)当前段的前几个3作为下一次解码的某一段的num,后面的一个3是letter,再后面的剩余的3作为下一次解码的number出现,比如前面有两个6,后年有两个4,即66633333344,下一次解码可能是

$\underset{66}{\underbrace{33........33}}\underset{33333}{\underbrace{44........44}}$ 前面必须有未使用完的数字作为num

$\underset{663}{\underbrace{33........33}}\underset{3333}{\underbrace{44........44}}$ 当前段还有数字作为后面的(即44)的num

$\underset{6633}{\underbrace{33........33}}\underset{333}{\underbrace{44........44}}$ 当前段还有数字作为后面的(即44)的num

$\underset{66333}{\underbrace{33........33}}\underset{33}{\underbrace{44........44}}$ 当前段还有数字作为后面的(即44)的num

$\underset{663333}{\underbrace{33........33}}\underset{3}{\underbrace{44........44}}$ 当前段还有数字作为后面的(即44)的num

$\underset{6633333}{\underbrace{33........33}}\underset{4}{\underbrace{44........44}}$ 当前段没有数字作为后面的(即44)的num

所以动态规划的状态需要保留两个信息:第一个,前一段第二次解码的letter是什么;第二,前面是否还有未使用的数字作为当前段的num。

code for problem1

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

public class InternetSecurity {


	public String[] determineWebsite(String[] address, String[] keyword, String[] dangerous, int threshold) {
		final int n = address.length;
		List<List<String>> keys = new ArrayList<>();
		for (int i = 0; i < n; ++ i) {
			List<String> list = new ArrayList<>();
			String[] p = keyword[i].split("\\W+");
			for (String s : p) {
				String t = s.trim();
				if (t.length() > 0) {
					list.add(t);
				}
			}
			keys.add(list);
		}

		Set<String> allDanger = new HashSet<>(Arrays.asList(dangerous));

		List<Integer> result = new ArrayList<>();
		boolean flag = true;
		boolean[] tag = new boolean[n];
		while (flag) {
			flag = false;
			for (int i = 0; i < n; ++ i) {
				if (tag[i]) {
					continue;
				}
				int cnt = 0;
				for (String s : keys.get(i)) {
					if (allDanger.contains(s)) {
						++ cnt;
						if (cnt >= threshold) {
							break;
						}
					}
				}
				if (cnt >= threshold) {
					result.add(i);
					flag = true;
					tag[i] = true;
					allDanger.addAll(keys.get(i));
				}
			}
		}
		Collections.sort(result);
		String[] ans = new String[result.size()];
		for (int i = 0; i < ans.length; ++ i) {
			ans[i] = address[result.get(i)];
		}
		return ans;
	}
}

  

code for problem2

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

public class NetworkSecurity {
	
	public int secureNetwork(String[] clientCable, String[] serverCable) {
		final int n = clientCable.length;
		final int m = serverCable[0].length();
		boolean[][] g = new boolean[n + m][n + m];
		for (int i = 0; i < n; ++ i) {
			for (int j = 0; j < n; ++ j) {
				if (clientCable[i].charAt(j) == 'Y') {
					g[i][j] =true;
				}
			}
			for (int j = 0; j < m; ++ j) {
				if (serverCable[i].charAt(j) == 'Y') {
					g[i][n + j] = true;
				}
			}
		}
		for (int i = 0; i < n + m; ++ i) {
			for (int j = 0; j < n + m; ++ j) {
				for (int k = 0; k < n + m; ++ k) {
					if (g[j][i] && g[i][k]) {
						g[j][k] = true;
					}
				}
			}
		}
		int result = 0;
		for (int i = 0; i < n; ++ i) {
			for (int j = 0; j < m; ++ j) {
				if (serverCable[i].charAt(j) == 'Y') {
					boolean tag = true;
					for (int k = 0; k < n; ++ k) {
						if (g[i][k] && g[k][n + j]) {
							tag = false;
							break;
						}
					}
					if (tag) {
						++ result;
					}
				}
			}
		}
		return result;
	}
}

  

code for problem3

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

public class StringDecryption {
	final static int mod = 1000000009;

	String S = null;

	public int decrypt(String[] code) {
		StringBuilder sb = new StringBuilder();
		for (String s: code) {
			sb.append(s);
		}
		S = sb.toString();
		final int n = S.length();
		long[][][] f = new long[n + 1][11][2];
		f[0][10][0] = 1;
		for (int i = 1; i <= n; ++ i) {
			final int cur = getChar(i);
			for (int j = 0; j <= i - 2; ++ j) {
				//当前段为{[j+1,i-1],i}
				//前一段为{[xxx,j-1],j}
				if (getChar(j + 1) == 0) {  //当前段个数不能有前导0
					continue;
				}
				if (getChar(j) == cur) {  //前一段跟当前段的数字不能相同
					continue;
				}
				final long X = get(j + 1, i - 1);
				for (int k = 0; k < 11; ++ k) {
					for (int t = 0; t < 2; ++ t) {
						if (cur == 0 && t == 0) {  //当前段数字为0时 第二次解码必定是跟前一段连在一起
							continue;                //因为对当前段第一次解码后 全是0
						}
						final long val = f[j][k][t];
						f[i][k][1] = (f[i][k][1] + val) % mod; //当前段直接作为开始或者是跟在前一段的开始
						if (k == cur) {
							continue;
						}
						if (cur > 0 && X > 1) {
							if (t == 1) {
								f[i][cur][1] = (f[i][cur][1] + val) % mod;
							}
							f[i][cur][1] += val * (X - 2) % mod;
							f[i][cur][1] %= mod;
						}
						if (X > 1 || t == 1) {  //最后一个数字作为结束
							f[i][cur][0] = (f[i][cur][0] + val) % mod;
						}
					}
				}
			}
		}
		long result = f[n][getChar(n)][0];
		if (result < 0) {
			result += mod;
		}
		return (int)result;
	}

	int getChar(int pos) {
		if (pos == 0) {
			return 10;
		}
		return S.charAt(pos - 1) - '0';
	}

	long get(int ll, int rr) {
		long result = 0;
		long b = 1;
		for (int i = rr; i >= ll; -- i) {
			result = calMod(result + b * getChar(i));
			b = calMod(b * 10);
		}
		return result;
	}

	long calMod(long x) {
		if (x >= mod) {
			x %= mod;
			if (x <= 1) {
				x += mod;
			}
		}
		return x;
	}
}

  

 

posted @ 2017-11-18 11:15  朝拜明天19891101  阅读(248)  评论(0编辑  收藏  举报