• UVa 658


    链接:

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=599

    题意:

    补丁在修正bug时,有时也会引入新的bug。假定有n(n≤20)个潜在bug和m(m≤100)个补丁,
    每个补丁用两个长度为n的字符串表示,其中字符串的每个位置表示一个bug。
    第一个串表示打补丁之前的状态(“-”表示该bug必须不存在,“+”表示必须存在,0表示无所谓),
    第二个串表示打补丁之后的状态(“-”表示不存在,“+”表示存在,0表示不变)。
    每个补丁都有一个执行时间,你的任务是用最少的时间把一个所有bug都存在的软件通过打补丁的方式变得没有bug。
    一个补丁可以打多次。

    分析:

    在任意时刻,每个bug可能存在也可能不存在,所以可以用一个n位二进制串表示当前软件的“状态”。
    打完补丁之后,bug状态会发生改变,对应“状态转移”。
    把状态看成结点,状态转移看成边,转化成图论中的最短路径问题,然后使用Dijkstra算法求解。
    不过这道题和普通的最短路径问题不一样:结点很多,多达2^n个,
    而且很多状态根本遇不到(即不管怎么打补丁,也不可能打成那个状态),所以没有必要先把图储存好。
    用隐式图搜索即可:当需要得到某个结点u出发的所有边时,直接枚举所有m个补丁,看看是否能打得上。

    代码:

     1 import java.io.*;
     2 import java.util.*;
     3 import static java.util.Arrays.*;
     4 
     5 public class Main {
     6     Scanner cin = new Scanner(new BufferedInputStream(System.in));
     7     final int INF = 0x3f3f3f3f;
     8     final int UPN = 20;
     9     final int UPM = 100;
    10     int n, m, sec[] = new int[UPM], d[] = new int[1<<UPN];
    11     char before[][] = new char[UPM][UPN], after[][] = new char[UPM][UPN];
    12     boolean done[] = new boolean[1<<UPN];
    13     
    14     class Node implements Comparable<Node> {
    15         int s, dist;
    16         
    17         Node(int s, int dist) {
    18             this.s = s;
    19             this.dist = dist;
    20         }
    21         
    22         @Override
    23         public int compareTo(Node that) {
    24             return dist - that.dist;
    25         }
    26     }
    27     
    28     int dijkstra() {
    29         fill(d, INF);
    30         fill(done, false);
    31         int ori = (1<<n) - 1;
    32         PriorityQueue<Node> Q = new PriorityQueue<Node>();
    33         d[ori] = 0;
    34         Q.add(new Node(ori, 0));
    35         while(Q.size() > 0) {
    36             Node cur = Q.poll();
    37             if(cur.s == 0) return cur.dist;
    38             if(done[cur.s]) continue;
    39             done[cur.s] = true;
    40             for(int t = 0; t < m; t++) {
    41                 boolean patchable = true;
    42                 for(int i = 0; i < n; i++) {
    43                     if(before[t][i] == '+' && (cur.s&(1<<i)) == 0) { patchable = false; break; }
    44                     else if(before[t][i] == '-' && (cur.s&(1<<i)) > 0) { patchable = false; break; }
    45                 }
    46                 if(!patchable) continue;
    47                 
    48                 Node temp = new Node(cur.s, cur.dist + sec[t]);
    49                 for(int i = 0; i < n; i++) {
    50                     if(after[t][i] == '+') temp.s |= (1<<i);
    51                     else if(after[t][i] == '-') temp.s &= ~(1<<i);
    52                 }
    53                 if(d[temp.s] > temp.dist) {
    54                     d[temp.s] = temp.dist;
    55                     Q.add(temp);
    56                 }
    57             }
    58         }
    59         return -1;
    60     }
    61     
    62     void MAIN() {
    63         for(int cases = 1; ; cases++) {
    64             n = cin.nextInt();
    65             m = cin.nextInt();
    66             if(n + m == 0) break;
    67             for(int i = 0; i < m; i++) {
    68                 sec[i] = cin.nextInt();
    69                 before[i] = cin.next().toCharArray();
    70                 after[i] = cin.next().toCharArray();
    71             }
    72             int ans = dijkstra();
    73             System.out.printf("Product %d
    ", cases);
    74             if(ans < 0) System.out.printf("Bugs cannot be fixed.
    
    ");
    75             else System.out.printf("Fastest sequence takes %d seconds.
    
    ", ans);
    76         }
    77     }
    78     
    79     public static void main(String args[]) { new Main().MAIN(); }
    80 }
  • 相关阅读:
    c#获得本月份是本季度的第几个月
    C#如何把月份转换成季度
    日本是如何处理地沟油的?
    惊艳的“学长帮我修电脑” VS “我想作你的下一行code”
    居然有人用腾讯QQ的申诉,来找回被盗的奇瑞QQ汽车[有图有真相]
    你长得够安全吗?
    这一刻我被深深地震精了![视频]Visual Studio最新"煽情"广告 让我做你下一行code
    打击地球人专用图
    ReportViewer的动态绑定
    纯天然的野菜居然会致癌?
  • 原文地址:https://www.cnblogs.com/hkxy125/p/9532356.html
Copyright © 2020-2023  润新知