poj3866 Exclusive Access 2

175 篇文章 0 订阅
125 篇文章 0 订阅

Description Having studied mutual exclusion protocols in the previous
year’s competition you are now facing a more challenging problem. You
have a big enterprise system with a number concurrently running
processes. The system has several resources - databases, message
queues, etc. Each concurrent process works with two resources at a
time. For example, one process might copy a job from a particular
database into the message queue, the other process might take a job
from the message queue, perform the job, and then put the result into
some other message queue, etc. All resources are protected from
concurrent access by mutual exclusion protocols also known as locks.
For example, to access a particular database process acquires the lock
for this database, then performs its work, then releases the lock. No
two processes can hold the same lock at the same time (that is the
property of mutual exclusion). Thus, the process that tries to acquire
a lock waits if that lock is taken by some other process. The main
loop of the process that works with resources P and Q looks like this:

loop forever

  DoSomeNonCriticalWork()

  P.lock()

  Q.lock()

  WorkWithResourcesPandQ()

  Q.unlock()

  P.unlock()

end loop

The order in which locks for resources P and Q are taken is important.
Consider a case where process c had acquired lock P with P.lock() and
is waiting for lock Q in Q.lock(). It means that lock Q is taken by
some other process d. If the process d is working (not waiting), then
we say that there is a wait chain of length 1. If d had acquired lock
Q and is waiting for another lock R, which is acquired by a working
process e, then we say that there is a wait chain of length 2, etc. If
any process in this wait chain waits for lock P that is already taken
by process c, then we say that the wait chain has infinite length and
the system deadlocks. For this problem, we are interested only in
alternating wait chains where processes hold their first locks and
wait for the second ones. Formally:

Alternating wait chain of length n (n >= 0) is an alternating sequence
of resources Ri (0 <= i <= n + 1) and distinct processes ci (0 <= i <=
n): R0 c0 R1 c1 … Rn cn Rn+1, where process ci acquires locks for
resources Ri and Ri+1 in this order. Alternating wait chain is a
deadlock when R0 = Rn+1.

You are given a set of resources each process works with. Your task is
to decide the order in which each process has to acquire its resource
locks, so that the system never deadlocks and the maximum length of
any possible alternating wait chain is minimized.

Input The first line of the input file contains a single integer n (1
<= n <= 100) - the number of processes. The following n lines describe
resources that each process needs. Each resource is designated with an
uppercase English letter from L to Z, so there are at most 15
resources. Each line describing process contains two different
resources separated by a space.

Output On first line of the output file write a singe integer number m
- the minimally possible length of the maximal alternating wait chain. Then write n lines - one line per process. On each line write two
resources in the order they should be taken by the corresponding
process to ensure this minimal length of the maximal alternating wait
chain. Separate resources on a line by a space. If there are multiple
satisfying orderings, then write any of them. The order of the
processes in the output should correspond to their order in the input.

题目描述比较绕,具体来说就是安排每个任务使用两个资源的顺序,使得在最坏情况下,当要执行一个工作时,需要等待的时间最短。
把资源看成点,任务看成无向边,任务就是把无向边定向,使图中不存在环而且最长链最短。
根据Dilworth定理【参见这里】,把点分成m部分,使每一部分内部没有边。m的最小值就是最长链的最小值。
状压dp即可求解图的着色问题。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
map<char,int> mp;
map<int,char> cv;
int n,m;
bool ok[1<<20],g[20][20];
int dp[1<<20],q1[110],q2[110],pre[1<<20],num[20];
int main()
{
    int i,j,k,u,v,clo;
    char s1[5],s2[5];
    scanf("%d",&m);
    for (i=1;i<=m;i++)
    {
        scanf("%s%s",s1,s2);
        if (!mp.count(s1[0])) cv[n]=s1[0],mp[s1[0]]=n++;
        if (!mp.count(s2[0])) cv[n]=s2[0],mp[s2[0]]=n++;
        u=mp[s1[0]];
        v=mp[s2[0]];
        q1[i]=u;
        q2[i]=v;
        g[u][v]=g[v][u]=1;
    }
    ok[0]=1;
    for (i=1;i<(1<<n);i++)
    {
        ok[i]=1;
        for (j=0;j<n;j++)
          if (i&(1<<j))
          {
            if (!ok[i^(1<<j)])
            {
                ok[i]=0;
                break;
            }
            for (k=0;k<n;k++)
              if (j!=k&&(i&(1<<k))&&g[j][k])
              {
                ok[i]=0;
                break;
              }
            break;
          }
    }
    memset(dp,0x3f,sizeof(dp));
    dp[0]=0;
    for (i=1;i<(1<<n);i++)
      for (j=i;j;j=i&(j-1))
        if (ok[j]&&dp[i^j]+1<dp[i])
        {
            dp[i]=dp[i^j]+1;
            pre[i]=j;
        }
    printf("%d\n",dp[(1<<n)-1]-2);
    for (i=(1<<n)-1,clo=1;i;i^=pre[i],clo++)
    {
        for (j=0;j<n;j++)
          if ((1<<j)&pre[i])
            num[j]=clo;
    }
    for (i=1;i<=m;i++)
      if (num[q1[i]]<num[q2[i]])
        printf("%c %c\n",cv[q1[i]],cv[q2[i]]);
      else
        printf("%c %c\n",cv[q2[i]],cv[q1[i]]);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值