A.传染病控制回到顶部
题意
给一棵树1为根被感染,每次切断一条边,然后从已经被感染的传播到相邻节点,若相连则被传染,问如何操作使得感人的人最少,n<=300
题解
考虑一个贪心做法,显然可以按照深度下来,求出每个点对应的深度,每次切对应深度的点儿子最多的树
显然这样并不能AC,考虑一种情况,一个节点一条链儿子最多,另一个节点分叉,那么如果切分叉,再来切链显然比贪心更优
那么就需要搜索所有的情况,显然按照贪心思路下来,获得的值较优,再来剪枝复杂度会大大降低,复杂度O(常数*n^2)
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.*; 2 3 public class Main { 4 5 private Scanner sc; 6 7 public static void main(String[] args) { 8 9 Scanner sc = new Scanner(System.in); 10 Solution solver = new Solution(); 11 solver.solve(sc); 12 } 13 14 } 15 16 class Solution { 17 18 private int[][] G = new int[305][305]; 19 private int[] sz = new int[305]; 20 private int[] deep = new int[305]; 21 private int[] father = new int[305]; 22 private boolean[] vis = new boolean[305]; 23 private int n, m, deaded; 24 public void solve(Scanner sc) { 25 n = sc.nextInt(); 26 m = sc.nextInt(); 27 for (int i = 0; i < m; i++) { 28 int u = sc.nextInt(); 29 int v = sc.nextInt(); 30 G[u][v] = G[v][u] = 1; 31 } 32 dfs(1, 1, 1); 33 deaded = n; 34 dep_dfs(1, 1); 35 System.out.println(deaded); 36 } 37 38 private void dfs(int u, int fa, int dep) { 39 sz[u] = 1; 40 deep[u] = dep; 41 father[u] = fa; 42 for (int v = 1; v <= n; v++) { 43 if (G[u][v] == 1 && v != fa) { 44 dfs(v, u, dep + 1); 45 sz[u] += sz[v]; 46 } 47 } 48 } 49 50 private void dep_dfs(int dep, int dead) { 51 if (dead >= deaded) return; 52 //处理一层节点 53 for (int i = 2; i <= n; i++) { 54 if (deep[i] == dep + 1) { 55 //System.out.println("i:" + i + " fa:" + father[i]); 56 //System.out.println("vis[i]:" + vis[i] + " vis[fa]:" + vis[father[i]]); 57 vis[i] = vis[father[i]]; 58 } 59 } 60 //sum代表这一层有多少个会死掉的节点 61 int sum = 0; 62 for (int i = 2; i <= n; i++) { 63 if (deep[i] == dep + 1 && !vis[i]) { 64 sum++; 65 } 66 } 67 //System.out.println("max:" + max); 68 //System.out.println("sum:" + sum); 69 //这一层所有的节点都活着,结束 70 if (sum == 0) { 71 //System.out.println("dead:" + dead); 72 deaded = Math.min(deaded, dead); 73 return; 74 } 75 //选择儿子最多的活下来 76 for (int i = 2; i <= n; i++) { 77 if (deep[i] == dep + 1 && !vis[i]) { 78 //System.out.println("cut:" + i); 79 vis[i] = true; 80 dep_dfs(dep + 1, dead + sum - 1); 81 vis[i] = false; 82 } 83 } 84 } 85 86 }
B.Billing Tables回到顶部
题意
n个电话,A - B 电话名,[A,B]的电话号表示改电话名,A,B代表的前缀可以合并,12300-12399可以合并为拨打123就可以知道对应电话名
拨一个电话按顺序下来查找对应电话名,其中电话名为invalid表示区间不可用
问这n个电话最少需要多少电话号表示
PS:题意看了n久n久
题解
显然字典树,我们需要把[A,B]区间插进去,很难做到吧
我们可以只插A和B,然后通过A往右,B往左圈定范围,每次把这个范围往下压
倒过来插入,这样可以覆盖掉原先标记的值,还要注意如果电话名相同可以会出现合并,就需要相同电话名标记相同
uL表示A当前的节点,uR表示B
1、如果uL=uR相当于父节点相同,所有子节点为nxt[uL][j]和nxt[uR][j],子节点只需要更新[L[i]+1,R[i]-1]这一段范围
1、为什么不把L[i]和R[i]更新了,因为最后需要遍历整颗树,遍历条件就是当前节点未被标记
2、但是根需要标记L[i]和R[i],这是结束遍历的标志,相当于尾部节点
2、如果uL和uR不相同,相当于uL更新[L[i]+1,9],uR更新[0,R[i]-1]
接下来要输出方案数,如果节点未被标记,往下遍历,如果已被标记,方案数加上1(如果合法)
由于需要求最少的前缀表示,那么就需要合并,可以知道如果某个节点的子节点0-9都合法,那么合并,合并只需要标记u为nxt[u][j],这样在搜索的时候下面就不会搜索而直接返回了
最后输出所有前缀表示,如果节点未被标记,往下遍历,如果已被标记则输出该方案
PS:好艰难意识模糊(看代码的debug就知道快炸了)
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.*; 2 3 public class Main { 4 5 private Scanner sc; 6 public static void main(String[] args) { 7 8 Scanner sc = new Scanner(System.in); 9 Solution solver = new Solution(); 10 solver.solve(sc); 11 } 12 13 } 14 15 class Solution { 16 17 private final int MAXN = 100005; 18 private final int CHAR_SIZE = 10; 19 20 private ArrayList<String> L = new ArrayList<>(); 21 private ArrayList<String> R = new ArrayList<>(); 22 private ArrayList<String> N = new ArrayList<>(); 23 private HashMap<String, Integer> hashMap = new HashMap<>(); 24 private int[] pl = new int[105]; // 处理相同名字N 25 private boolean[] vis = new boolean[105];// 是否非法 26 private int[] mark = new int[MAXN]; // 节点标记【可能是一个区间】,用于计数 27 private int[][] nxt = new int[MAXN][CHAR_SIZE]; 28 private char[] out = new char[13]; 29 private int tot, ans; 30 31 public void solve(Scanner sc) { 32 int n = sc.nextInt(); 33 sc.nextLine(); // 读回车 34 L.add("");R.add("");N.add(""); 35 for (int i = 1; i <= n; i++) { 36 String s = sc.nextLine(); 37 String[] str = s.split(" "); 38 // 对齐 39 StringBuilder sb = new StringBuilder(); 40 for (int j = 0; j < str[0].length() - str[2].length(); j++) 41 sb.append(str[0].charAt(j)); 42 sb.append(str[2]); 43 L.add(str[0]); 44 R.add(sb.toString()); 45 N.add(str[3]); 46 //System.out.println(str[0]); 47 //System.out.println(sb.toString()); 48 //System.out.println(str[3]); 49 vis[i] = !("invalid".equals(str[3])); 50 //System.out.println(vis[i]); 51 if (hashMap.containsKey(str[3])) { 52 // 名字相同可合并 53 pl[i] = hashMap.get(str[3]); 54 } 55 else { 56 pl[i] = i; 57 hashMap.put(str[3], i); 58 } 59 } 60 61 // root = 0; 62 for (int i = n; i >= 1; i--) { 63 insert(i); 64 } 65 // 计数 66 dfs1(0); 67 System.out.println(ans); 68 69 // 输出路径 70 dfs2(0, 0); 71 } 72 73 private void insert(int pos) { 74 //System.out.println("pos:" + pos + " pl:" + pl[pos]); 75 int uL = 0, uR = 0; 76 for (int i = 0; i < L.get(pos).length(); i++) { 77 // 当前父节点u如果有标记,传递标记 78 for (int j = 0; j < CHAR_SIZE; j++) { 79 if (nxt[uL][j] == 0) nxt[uL][j] = ++tot; 80 if (nxt[uR][j] == 0) nxt[uR][j] = ++tot; 81 if (mark[uL] > 0) mark[nxt[uL][j]] = mark[uL]; 82 if (mark[uR] > 0) mark[nxt[uR][j]] = mark[uR]; 83 } 84 85 mark[uL] = mark[uR] = 0; 86 if (uL == uR) { 87 // 如果父节点u相同,子节点可以一起更新 88 // 子节点标记markId 89 for (int j = L.get(pos).charAt(i) - '0' + 1; j < R.get(pos).charAt(i) - '0'; j++) 90 mark[nxt[uL][j]] = pl[pos]; 91 } else { 92 // 如果父节点u不同,左子节点到L[i]+1 - 9,右子节点到0 - R[i]-1 93 for (int j = L.get(pos).charAt(i) - '0' + 1; j < CHAR_SIZE; j++) 94 mark[nxt[uL][j]] = pl[pos]; 95 for (int j = 0; j < R.get(pos).charAt(i) - '0'; j++) 96 mark[nxt[uR][j]] = pl[pos]; 97 } 98 //System.out.println("uL:" + uL + " uR:" + uR); 99 uL = nxt[uL][L.get(pos).charAt(i) - '0']; 100 uR = nxt[uR][R.get(pos).charAt(i) - '0']; 101 } 102 // 若循环结束,标记当前节点为尾部节点 103 mark[uL] = pl[pos]; 104 mark[uR] = pl[pos]; 105 } 106 107 private void dfs1(int u) { 108 // 如果节点被标记 109 // 1、区间内的节点 110 // 2、搜索尾部节点 111 if (mark[u] > 0) { 112 int add = vis[mark[u]] ? 1 : 0; 113 //System.out.println("u:" + u + " add:" + add); 114 ans += add; 115 return; 116 } 117 if (nxt[u][0] == 0) return; 118 119 //儿子个数,如果为10个则合并 120 boolean f = true; 121 for (int i = 0; i < CHAR_SIZE; i++) { 122 dfs1(nxt[u][i]); 123 if (mark[nxt[u][i]] != mark[nxt[u][0]]) f = false; 124 } 125 if (f && vis[mark[nxt[u][0]]] && u != 0) { 126 ans -= 9; 127 mark[u] = mark[nxt[u][0]]; 128 } 129 } 130 131 private void dfs2(int u, int p) { 132 int add = vis[mark[u]] ? 1 : 0; 133 if (mark[u] > 0) { 134 if (add != 0) { 135 for (int i = 0; i < p; i++) { 136 System.out.print(out[i]); 137 } 138 System.out.print(' '); 139 System.out.println(N.get(mark[u])); 140 } 141 return; 142 } 143 if (nxt[u][0] == 0) return; 144 for (int i = 0; i < CHAR_SIZE; i++) { 145 out[p] = (char) (i + '0'); 146 dfs2(nxt[u][i], p + 1); 147 } 148 } 149 }
C.Arithmetic Progression回到顶部
题意
n个数,求最长连续递增子串,n<=100000
题解
对原数组做一次差分即a[i]=a[i]-a[i-1],求得最长连续相同子串,注意n=1输出1,复杂度O(n)
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.*; 2 3 public class Main { 4 5 private Scanner sc; 6 7 public static void main(String[] args) { 8 9 Scanner sc = new Scanner(System.in); 10 Solution solver = new Solution(); 11 solver.solve(sc); 12 } 13 14 } 15 16 class Solution { 17 18 public void solve(Scanner sc) { 19 while (sc.hasNext()) { 20 int n = sc.nextInt(); 21 int[] a = new int[n]; 22 int last = 0; 23 for (int i = 0; i < n; i++) { 24 int x = sc.nextInt(); 25 if (i > 0) 26 a[i] = x - last; 27 last = x; 28 } 29 //System.out.println(Arrays.toString(a)); 30 if (n <= 2) { 31 System.out.println(n); 32 continue; 33 } 34 int maxLen = 0; 35 for (int i = 1; i < n; i++) { 36 int Len = 0; 37 while (i + Len + 1 < n && a[i + Len + 1] == a[i]) { 38 Len++; 39 } 40 i += Len; 41 maxLen = Math.max(maxLen, Len + 2); 42 } 43 System.out.println(maxLen); 44 } 45 } 46 47 }
D.To be a Palindrome回到顶部
题意
给一个长度<=100的串,接上一个最短的串使得回文
题解
长度很短,直接暴力把所有情况枚举一下,复杂度O(100^2)
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.*; 2 3 public class Main { 4 5 private Scanner sc; 6 7 public static void main(String[] args) { 8 9 Scanner sc = new Scanner(System.in); 10 Solution solver = new Solution(); 11 solver.solve(sc); 12 } 13 14 } 15 16 class Solution { 17 18 public void solve(Scanner sc) { 19 while (sc.hasNext()) { 20 String s = sc.next(); 21 if (check(s)) { 22 System.out.println(s); 23 continue; 24 } 25 for (int i = 0; i < s.length(); i++) { 26 String s1 = s + reverse(s.substring(0, i + 1)); 27 if (check(s1)) { 28 System.out.print(s1); 29 break; 30 } 31 } 32 System.out.println(); 33 } 34 } 35 36 private boolean check(String s) { 37 for(int L = 0, R = s.length() - 1; L < R; L++, R--) { 38 if (s.charAt(L) != s.charAt(R)) 39 return false; 40 } 41 return true; 42 } 43 44 private String reverse(String s) { 45 StringBuilder sb = new StringBuilder(); 46 for (int i = s.length() - 1; i >= 0; i--) { 47 sb.append(s.charAt(i)); 48 } 49 return sb.toString(); 50 } 51 }
E.Railroad回到顶部
题意
给两个队列,问能否构造出一个队列满足条件,n<=1000
题解
dp[i][j][k]表示第一个队列到i,第二个队列到j,答案队列到k
显然已知i和j,那么k固定,所以dp[i][j]即可
那么合法的方案数为1000^2个,那么直接深搜即可解决,复杂度O(n^2)
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.*; 2 3 public class Main { 4 5 private Scanner sc; 6 7 public static void main(String[] args) { 8 9 Scanner sc = new Scanner(System.in); 10 Solution solver = new Solution(); 11 solver.solve(sc); 12 } 13 14 } 15 16 class Solution { 17 18 private int[] a; 19 private int[] b; 20 private int[] c; 21 private boolean[][] vis; 22 private boolean f; 23 private int n1, n2; 24 25 public void solve(Scanner sc) { 26 while (sc.hasNext()) { 27 n1 = sc.nextInt(); 28 n2 = sc.nextInt(); 29 if (n1 == 0 && n2 == 0) break; 30 a = new int[n1]; 31 b = new int[n2]; 32 c = new int[n1 + n2]; 33 vis = new boolean[n1 + 5][n2 + 5]; 34 for (int i = 0; i < n1; i++) a[i] = sc.nextInt(); 35 for (int i = 0; i < n2; i++) b[i] = sc.nextInt(); 36 for (int i = 0; i < n1 + n2; i++) c[i] = sc.nextInt(); 37 f = false; 38 dfs(0, 0, 0); 39 System.out.println(f ? "possible" : "not possible"); 40 } 41 } 42 43 private void dfs(int na, int nb, int nc) { 44 if (nc == n1 + n2 || f) { 45 f = true; 46 } else if (!vis[na][nb]){ 47 vis[na][nb] = true; 48 if (na < n1 && c[nc] == a[na]) 49 dfs(na + 1, nb, nc + 1); 50 if (nb < n2 && c[nc] == b[nb]) 51 dfs(na, nb + 1, nc + 1); 52 } 53 } 54 }
F.统计数字个数回到顶部
题意
给n个数,求合法数字个数(数字中可能夹杂着错误符号,但不会包含小数点、空格等,也不会出现有前导符0的的情况如0123或-0123等,每个数字长度不超过10)
题解
题意数据的构造,按照题意判断,复杂度O(1)
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.*; 2 3 public class Main { 4 5 private Scanner sc; 6 7 public static void main(String[] args) { 8 9 Scanner sc = new Scanner(System.in); 10 Solution solver = new Solution(); 11 solver.solve(sc); 12 } 13 14 } 15 16 class Solution { 17 18 public void solve(Scanner sc) { 19 while (sc.hasNext()) { 20 int n = sc.nextInt(); 21 int cnt = 0; 22 boolean f; 23 for (int i = 0; i < n; i++) { 24 String s = sc.next(); 25 f = true; 26 if (!(s.charAt(0) == '-' || s.charAt(0) >= '0' && s.charAt(0) <= '9')) f = false; 27 for (int j = 1; j < s.length(); j++) if (!(s.charAt(j) >= '0' && s.charAt(j) <= '9')) f = false; 28 if (f) cnt++; 29 } 30 System.out.println(cnt); 31 } 32 } 33 34 }
G.文化之旅回到顶部
题意
n个点m条边,每个点有一个文化,对于(u,v,w)如果文化不同则连通,问S->T的最短路,n,k<=100,m<=n^2
题解
n只有100,直接floyd算出任意两点的最短路,直接搜索,复杂度O(n^3)
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.*; 2 3 public class Main { 4 5 private Scanner sc; 6 7 public static void main(String[] args) { 8 9 Scanner sc = new Scanner(System.in); 10 Solution solver = new Solution(); 11 solver.solve(sc); 12 } 13 14 } 15 16 class Solution { 17 18 private final int MAXN = 105; 19 20 private int N, K, M, S, T, u, v, w, ans; 21 private int[][] a = new int[MAXN][MAXN]; 22 private int[][] d = new int[MAXN][MAXN]; 23 private int[][] G = new int[MAXN][MAXN]; 24 private int[] c = new int[MAXN]; 25 private boolean[] vis = new boolean[MAXN]; 26 27 void dfs(int u, int dis) { 28 if (dis + d[u][T] >= ans) return; 29 if (u == T) { 30 ans = Math.min(ans, dis); 31 return; 32 } 33 for (int v = 1; v <= N; v++) { 34 if (a[c[v]][c[u]] == 0 && !vis[c[v]]) { 35 vis[c[v]] = true; 36 dfs(v, dis + G[u][v]); 37 vis[c[v]] = false; 38 } 39 } 40 } 41 42 public void solve(Scanner sc) { 43 N = sc.nextInt(); 44 K = sc.nextInt(); 45 M = sc.nextInt(); 46 S = sc.nextInt(); 47 T = sc.nextInt(); 48 49 for (int i = 1; i <= N; i++) 50 for (int j = 1; j <= N; j++) 51 d[i][j] = G[i][j] = 0x3f3f3f3f; 52 53 for (int i = 1; i <= N; i++) { 54 c[i] = sc.nextInt(); 55 G[i][i] = d[i][i] = 0; 56 } 57 for (int i = 1; i <= K; i++) 58 for (int j = 1; j <= K; j++) 59 a[i][j] = sc.nextInt(); 60 61 for (int i = 1; i <= M; i++) { 62 u = sc.nextInt(); 63 v = sc.nextInt(); 64 w = sc.nextInt(); 65 if (a[c[u]][c[v]] == 0 && c[u] != c[v]) G[v][u] = d[v][u] = Math.min(d[v][u], w); 66 if (a[c[v]][c[u]] == 0 && c[u] != c[v]) G[u][v] = d[u][v] = Math.min(d[u][v], w); 67 } 68 69 //floyd 70 for (int k = 1; k <= N; k++) 71 for (int i = 1; i <= N; i++) 72 for (int j = 1; j <= N; j++) 73 if (a[c[k]][c[i]] == 0 && a[c[j]][c[k]] == 0 && d[i][j] > d[i][k] + d[k][j]) 74 d[i][j] = d[i][k] + d[k][j]; 75 76 for (int i = 1; i <= N; i++) 77 vis[i] = false; 78 ans = 0x3f3f3f3f; 79 vis[c[S]] = true; 80 dfs(S, 0); 81 if (ans == 0x3f3f3f3f) System.out.println(-1); 82 else System.out.println(ans); 83 } 84 85 }
H.同花顺2回到顶部
题意
给一副牌,判断是否同花顺
题解
模拟,求出花色对应的点数,判断连续5个是否合法,细节题,复杂度O(n)
PS:一度空指针异常,原来是对象数组得new两次,一次是指针空间,一次是对象空间
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.*; 2 3 public class Main { 4 5 private Scanner sc; 6 7 public static void main(String[] args) { 8 9 Scanner sc = new Scanner(System.in); 10 Solution solver = new Solution(); 11 solver.solve(sc); 12 } 13 14 } 15 16 class Solution { 17 18 class Pai { 19 int f, ds; 20 } 21 22 public void solve(Scanner sc) { 23 while (sc.hasNext()) { 24 int n = sc.nextInt(); 25 Pai[] pai = new Pai[100]; 26 for (int i = 0; i < 100; i++) { 27 pai[i] = new Pai(); 28 pai[i].f = pai[i].ds = 0; 29 } 30 for (int i = 0; i < n; i++) { 31 String hs = sc.next(); 32 if (hs.charAt(0) == 'S') 33 pai[i].f = 1; 34 else if (hs.charAt(0) == 'H') 35 pai[i].f = 2; 36 else if (hs.charAt(0) == 'C') 37 pai[i].f = 3; 38 else if (hs.charAt(0) == 'D') 39 pai[i].f = 4; 40 if (hs.charAt(1) == '1' && hs.charAt(2) == '0') 41 pai[i].ds = 10; 42 else if (hs.charAt(1) >= '0' && hs.charAt(1) <= '9') 43 pai[i].ds = hs.charAt(1) - '0'; 44 else if (hs.charAt(1) == 'J') 45 pai[i].ds = 11; 46 else if (hs.charAt(1) == 'Q') 47 pai[i].ds = 12; 48 else if (hs.charAt(1) == 'K') 49 pai[i].ds = 13; 50 else if (hs.charAt(1) == 'A') 51 pai[i].ds = 14; 52 } 53 List<Integer> b = new ArrayList<>(); 54 List<Integer> c = new ArrayList<>(); 55 List<Integer> d = new ArrayList<>(); 56 List<Integer> e = new ArrayList<>(); 57 for (int i = 0; i < n; i++) { 58 if (pai[i].f == 1) 59 b.add(pai[i].ds); 60 if (pai[i].f == 2) 61 c.add(pai[i].ds); 62 if (pai[i].f == 3) 63 d.add(pai[i].ds); 64 if (pai[i].f == 4) 65 e.add(pai[i].ds); 66 } 67 68 if (check(b) || check(c) || check(d) || check(e)) 69 System.out.println("Yes"); 70 else 71 System.out.println("No"); 72 } 73 } 74 75 private boolean check(List<Integer> a) { 76 int n = a.size(); 77 if (n <= 4) return false; 78 Collections.sort(a); 79 for (int i = 0; i <= n - 5; i++) { 80 if (a.get(i) != 2) { 81 boolean f = true; 82 for (int j = i + 1; j <= i + 4; j++) { 83 if (a.get(j) - a.get(j - 1) != 1) 84 f = false; 85 } 86 if (f) return true; 87 } 88 } 89 return false; 90 } 91 }
I.Parallel computer simulator回到顶部
题意
背景:操作系统CPU切换执行不同程序
n段程序,每段end结束,5种语句分别为a = 1(只有26个变量,赋值<=1000),print a,lock,unlock,end和各自需要执行的时间,再给一个t表示一次单位时间。每次取出就绪队列首部程序id执行一个单位时间;
1、一次单位时间内可以执行多条语句;
2、若单位时间内单位语句未执行完则等到其执行完;
3、若获取lock失败则不会执行其他语句;
4、若unlock则从阻塞队列获得第一个程序id放入就绪队列
5、若程序id还有语句未执行则放入就绪队列尾部
n<=100,单个程序语句数<=200
PS:题意够长够恶心
题解
直接按照题意模拟,双端队列代表就绪队列,队列代表阻塞队列,复杂度O(100*200)
PS:查了一下java中的双端队列和阻塞队列,ConcurrentLinkedDeque(Queue),JDK1.7 JUC包引入,采用无锁算法,底层使用自旋+CAS的方式实现非阻塞来保证线程并发访问时的数据一致性
但是它的迭代器是弱一致性的,不能保证完全一致性。例如一个线程在遍历,另一个线程在修改不会抛出异常
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.*; 2 import java.util.concurrent.ConcurrentLinkedDeque; 3 import java.util.concurrent.ConcurrentLinkedQueue; 4 5 public class Main { 6 7 private Scanner sc; 8 public static void main(String[] args) { 9 10 Scanner sc = new Scanner(System.in); 11 Solution solver = new Solution(); 12 solver.solve(sc); 13 } 14 15 } 16 17 class Solution { 18 19 private int[] t = new int[5]; 20 private List< List<String> > list = new ArrayList<>(); 21 private int[] list_pos = new int[205]; 22 private int[] val = new int[26]; 23 private ConcurrentLinkedDeque<Integer> ready = new ConcurrentLinkedDeque<>(); 24 private ConcurrentLinkedQueue<Integer> block = new ConcurrentLinkedQueue<>(); 25 public void solve(Scanner sc) { 26 int n = sc.nextInt(); 27 for (int i = 0; i < 5; i++) t[i] = sc.nextInt(); 28 int time = sc.nextInt(); 29 sc.nextLine();// 读回车 30 for (int i = 0; i < n; i++) { 31 list.add(new ArrayList<>()); 32 ready.addLast(i); 33 while (true) { 34 String s = sc.nextLine(); 35 list.get(i).add(s); 36 if ("end".equals(s)) break; 37 } 38 } 39 // 是否阻塞 40 boolean blocked = false; 41 while (!ready.isEmpty()) { 42 int id = ready.getFirst(); 43 ready.removeFirst(); 44 int time_cur = time; 45 // 是否能够继续运行 46 boolean ok = true; 47 // 当前程序执行一段时间 48 do { 49 String exec = list.get(id).get(list_pos[id]); 50 char ch = exec.charAt(2); 51 if (ch == '=') { 52 // a = 4 53 time_cur -= t[0]; 54 String cut = exec.substring(4); 55 val[exec.charAt(0) - 'a'] = Integer.parseInt(cut); 56 } else if (ch == 'i') { 57 // print a 58 time_cur -= t[1]; 59 System.out.printf("%d: %d ", id + 1, val[exec.charAt(6) - 'a']); 60 } else if (ch == 'c') { 61 // lock 62 // 获取lock成功 63 time_cur -= t[2]; 64 // 获取lock失败,当前程序停止,进入阻塞队列 65 if (blocked) { 66 block.add(id); 67 time_cur = 0; 68 ok = false; 69 } 70 blocked = true; 71 } else if (ch == 'l') { 72 // unlock 73 time_cur -= t[3]; 74 // 若阻塞队列有,移除开头放入就绪队列头 75 if (!block.isEmpty()) { 76 ready.addFirst(block.element()); 77 block.remove(); 78 } 79 blocked = false; 80 } else if (ch == 'd') { 81 // end 82 time_cur = 0; 83 } 84 // 如果当前语句调用成功 85 if (ok) list_pos[id]++; 86 } while (time_cur > 0); 87 88 // 如果能够继续运行,并且没到end,放回 89 if (ok && list_pos[id] != list.get(id).size()) { 90 ready.addLast(id); 91 } 92 } 93 } 94 95 }
J.简单21点游戏回到顶部
题意
给n张牌,判断和21的关系
题解
按题意来,复杂度O(n)
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.util.*; 2 3 public class Main { 4 5 private Scanner sc; 6 7 public static void main(String[] args) { 8 9 Scanner sc = new Scanner(System.in); 10 Solution solver = new Solution(); 11 solver.solve(sc); 12 } 13 14 } 15 16 class Solution { 17 18 public void solve(Scanner sc) { 19 int n = sc.nextInt(); 20 int sum = 0; 21 for (int i = 0; i < n; i++) { 22 int card = sc.nextInt(); 23 sum += card; 24 } 25 if (sum == 21) System.out.println("Yes"); 26 else if (sum < 21 &&Math.abs(sum - 21) <= 5) System.out.printf("Just so so %d", Math.abs(sum - 21)); 27 else System.out.printf("No %d", Math.abs(sum - 21)); 28 } 29 30 }