• 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} e 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;
    	}
    }
    

      

  • 相关阅读:
    UVALive-8077 Brick Walls 找规律
    UVALive-8079 Making a Team 排列组合公式化简
    UVALive-8072 Keeping On Track 树形dp 联通块之间缺失边的个数
    HDU-5534 Partial Tree 完全背包 设定初始选择
    HDU-2844 Coins 多重背包 物品数量二进制优化
    CodeForces-366C Dima and Salad 对01背包的理解 多个背包问题
    HDU-2955 Robberies 浮点数01背包 自变量和因变量位置互换
    UVALive-7197 Axles 动态规划 多个背包问题
    广义表(C++实现)
    稀疏矩阵及稀疏矩阵的压缩存储
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/7856211.html
Copyright © 2020-2023  润新知