zoukankan      html  css  js  c++  java
  • uva1439 Exclusive Access 2

    感觉这道题读题有点难。。似乎和现实联系的比较密切
    1.每个process的两个资源可以顺序反一下
    2.p->q,q->s不可以同时进行
    p->q,p->s可以

    输出最长等待链
    输出每个process的资源调用顺序 (注意按输入顺序输出,并不意味着按输入顺序先后执行,只是输出方便看)

    把资源看成点,一个process就成了链接两个点的无向边
    任务就成了把无向边定向,使其不存在圈,且最长路(也即最长等待链最短)

    创造性思维:把结点分成p层,编号为0,1,2...使同层结点间没有边;对任意边u-v,定向位从层编号小的点指向层编号大的点。
    则定向后的图肯定没有圈,且最长路所含点数不超过p。所以p越小越好(直观上)

    可以证明p取得最小值时,最长路恰好包含p个结点,且这个结果是所有定向方案中最优的。 (证明:从定向方案构造分层图。先把所有路径的起点作为第0层。 (没证!!!))

    这样问题转化为结点分层问题。也就是色数问题:将图中结点染成尽量小的颜色,使相邻结点颜色不同。
    (色数问题见紫书P286)
    O(3^K)k<=15.

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    // Here n is the number of resources, m is the number of processes (n in the problem statement)
    const int maxn = 15;
    const int maxm = 100 + 5;
    int n, m, u[maxm], v[maxm], G[maxn][maxn];
    int ind[1<<maxn], d[1<<maxn], best[1<<maxn], label[maxn];
    
    bool independent(int mask) {
      for(int i = 0; i < maxn; i++) if(mask & (1<<i))
        for(int j = 0; j < maxn; j++) if(mask & (1<<j))
          if(i != j && G[i][j]) return false;
      return true;
    }
    
    // How many colors are needed to color the set 'mask'
    int dp(int mask) {
      int& ans = d[mask];
      if(ans >= 0) return ans;
      if(mask == 0) return 0;
      ans = maxn+1;
      for(int s = mask; s; s = (s-1)&mask)
        if(ind[s]) {
          int v = dp(mask^s) + 1;
          if(v < ans) { ans = v; best[mask] = s; }
        }
      return ans;
    }
    
    // mark the set 'mask' with color c
    void mark(int mask, int c) {
      for(int i = 0; i < maxn; i++)
        if(mask & (1<<i)) label[i] = c;
    }
    
    int main() {
      while(scanf("%d", &m) == 1) {
        memset(G, 0, sizeof(G));
        int useful = 0;
        for(int i = 0; i < m; i++) {
          char r1[9], r2[9];
          scanf("%s%s", r1, r2);
          u[i] = r1[0]-'L', v[i] = r2[0]-'L';
          G[u[i]][v[i]] = 1;
          useful |= (1<<u[i]);
          useful |= (1<<v[i]);
        }
    
        // find the independent sets
        memset(ind, 0, sizeof(ind));
        for(int s = useful; s; s = (s-1)&useful)
          if(independent(s)) ind[s] = true;
    
        // dp
        memset(d, -1, sizeof(d));
        int ans = dp(useful);
        printf("%d
    ", ans-2);
    
        // construct the answer
        int s = useful, k = 0;
        while(s) {
          mark(s, k++);
          s ^= best[s];
        }
        for(int i = 0; i < m; i++) {
          if(label[u[i]] < label[v[i]]) swap(u[i], v[i]);
          printf("%c %c
    ", 'L'+u[i], 'L'+v[i]);
        }
      }
      return 0;
    }
  • 相关阅读:
    目前正在自学python,前几天做了一个比较简单的坦克大战游戏,分享出来,想搞一搞的朋友,可以参考。
    我今天给学习运维而英语不好的各位,提供一些计算机英语,感谢惨绿少年的原文和已经离开身边提供英标部分的小虾大佬,只是为了记录。
    前几天看见pthon自动跳一跳很火,自己也按捺不住寂寞,实现了一把。分享一下。图文详解,如果有问题留言,帮解决。
    day01
    java之jvm篇
    mysql
    leecode刷题——数组篇
    java基础
    python进程和线程
    python I/O编程
  • 原文地址:https://www.cnblogs.com/lqerio/p/9800752.html
Copyright © 2011-2022 走看看