TZOJ 挑战题库随机训练09(JAVA)

点击题号跳转

A4789 B1123 C4266 D3672 E3412

F5360 G4871 H5331 I2291 J5610

A.传染病控制回到顶部

题意

给一棵树1为根被感染,每次切断一条边,然后从已经被感染的传播到相邻节点,若相连则被传染,问如何操作使得感人的人最少,n<=300

题解

考虑一个贪心做法,显然可以按照深度下来,求出每个点对应的深度,每次切对应深度的点儿子最多的树

显然这样并不能AC,考虑一种情况,一个节点一条链儿子最多,另一个节点分叉,那么如果切分叉,再来切链显然比贪心更优

那么就需要搜索所有的情况,显然按照贪心思路下来,获得的值较优,再来剪枝复杂度会大大降低,复杂度O(常数*n^2)

代码

 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 }
A

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就知道快炸了)

代码

  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 }
B

C.Arithmetic Progression回到顶部

题意

n个数,求最长连续递增子串,n<=100000

题解

对原数组做一次差分即a[i]=a[i]-a[i-1],求得最长连续相同子串,注意n=1输出1,复杂度O(n)

代码

 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 }
C

D.To be a Palindrome回到顶部

题意

给一个长度<=100的串,接上一个最短的串使得回文

题解

长度很短,直接暴力把所有情况枚举一下,复杂度O(100^2)

代码

 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 }
D

E.Railroad回到顶部

题意

给两个队列,问能否构造出一个队列满足条件,n<=1000

题解

dp[i][j][k]表示第一个队列到i,第二个队列到j,答案队列到k

显然已知i和j,那么k固定,所以dp[i][j]即可

那么合法的方案数为1000^2个,那么直接深搜即可解决,复杂度O(n^2)

代码

 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 }
E

F.统计数字个数回到顶部

题意

给n个数,求合法数字个数(数字中可能夹杂着错误符号,但不会包含小数点、空格等,也不会出现有前导符0的的情况如0123或-0123等,每个数字长度不超过10)

题解

题意数据的构造,按照题意判断,复杂度O(1)

代码

 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 }
F

G.文化之旅回到顶部

题意

n个点m条边,每个点有一个文化,对于(u,v,w)如果文化不同则连通,问S->T的最短路,n,k<=100,m<=n^2

题解

n只有100,直接floyd算出任意两点的最短路,直接搜索,复杂度O(n^3)

代码

 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 }
G

H.同花顺2回到顶部

题意

给一副牌,判断是否同花顺

题解

模拟,求出花色对应的点数,判断连续5个是否合法,细节题,复杂度O(n)

PS:一度空指针异常,原来是对象数组得new两次,一次是指针空间,一次是对象空间

代码

 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 }
H

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的方式实现非阻塞来保证线程并发访问时的数据一致性

但是它的迭代器是弱一致性的,不能保证完全一致性。例如一个线程在遍历,另一个线程在修改不会抛出异常

代码

 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 }
I

J.简单21点游戏回到顶部

题意

给n张牌,判断和21的关系

题解

按题意来,复杂度O(n)

代码

 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 }
J
原文地址:https://www.cnblogs.com/taozi1115402474/p/12734925.html