zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    房价
    Jsrender初体验
    GCD XOR UVA
    GCD
    Aladdin and the Flying Carpet LightOJ
    HDU6035 2017多校第一场1003 树形DP
    F
    C
    B
    An Easy Physics Problem HDU
  • 原文地址:https://www.cnblogs.com/taozi1115402474/p/12734925.html
Copyright © 2011-2022 走看看