BZOJ 1198 [HNOI2006]军机调度:dfs

Posted Leohh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 1198 [HNOI2006]军机调度:dfs相关的知识,希望对你有一定的参考价值。

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1198

题意:

  有n个雇佣军,m个任务。

  第i个雇佣军能够参加cnt个任务,分别为temp[0 to cnt-1]。

  第i个任务开始时间为start[i],结束时间为over[i],需要person[i]个人参加才能够完成,完成的报酬为reward[i]。

  一项只需要n个人来完成的任务,如果执行该任务的人数p大于n,那么反而会得到更少的报酬,即原报酬的1/(p-n+1)。

  一个人不能同时执行两项任务,也不能中途加入或者退出任务。但可以不执行任何任务。

  问你能够获得的最大报酬。

 

题解:

  dfs暴搜。。。

 

  表示状态:

    dfs(mis, per, now, val)

    mis:考虑到第mis个任务

    per:考虑到第per个人

    now:已经参加任务mis的人数

    val:已经获得的报酬(不算mis)

 

  dfs:

    首先按任务的start从小到大排序。

    (1)mis == m:

        搜到底了,更新ans = max val。

 

    (2)per == n || now == mission[mis].person:

        per == n 表示没有人可选了

        now == mission[mis].person 表示人数已经达到任务mis的要求,再加人报酬会变小,不加人可能使答案更优。

        此时进入到下一个任务 mis + 1,然后return当前的dfs(不存在)。

    (3)fre[per] < mission[mis].start  &&  edge[per][mission[mis].idx]

        数组fre[per]代表在之前的决策中,士兵per所执行任务的最后一天。

        fre[per] < mission[mis].start:任务mis开始时,士兵per之前的任务已结束。

        edge[per][mission[mis].idx]:士兵per可以参加任务mis。

        若满足,则让士兵per参加mis。更新fre[per],dfs(mis,per+1,now+1,val),然后恢复fre。

    (4)dfs(mis,per+1,now,val):

        也可以不选per。

 

AC Code:

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <algorithm>
  5 #define MAX_N 15
  6 #define MAX_M 20
  7 
  8 using namespace std;
  9 
 10 struct Mission
 11 {
 12     int start;
 13     int over;
 14     int person;
 15     int reward;
 16     int idx;
 17     Mission(int _start,int _over,int _person,int _reward,int _idx)
 18     {
 19         start=_start;
 20         over=_over;
 21         person=_person;
 22         reward=_reward;
 23         idx=_idx;
 24     }
 25     Mission(){}
 26     void read_mission(int _idx)
 27     {
 28         cin>>start>>over>>person>>reward;
 29         idx=_idx;
 30     }
 31     friend bool operator < (const Mission &a,const Mission &b)
 32     {
 33         return a.start<b.start;
 34     }
 35 };
 36 
 37 int n,m;
 38 int ans=0;
 39 int fre[MAX_N];
 40 bool edge[MAX_N][MAX_M];
 41 Mission mission[MAX_M];
 42 
 43 void read()
 44 {
 45     memset(edge,false,sizeof(edge));
 46     cin>>n>>m;
 47     for(int i=0;i<n;i++)
 48     {
 49         int counter;
 50         cin>>counter;
 51         for(int j=0;j<counter;j++)
 52         {
 53             int temp;
 54             cin>>temp;
 55             edge[i][temp-1]=true;
 56         }
 57     }
 58     for(int i=0;i<m;i++)
 59     {
 60         mission[i].read_mission(i);
 61     }
 62 }
 63 
 64 void dfs(int mis,int per,int now,int val)
 65 {
 66     if(mis==m)
 67     {
 68         ans=max(ans,val);
 69         return;
 70     }
 71     if(per==n || now==mission[mis].person)
 72     {
 73         int adv=(now==mission[mis].person?mission[mis].reward:0);
 74         dfs(mis+1,0,0,val+adv);
 75         return;
 76     }
 77     if(fre[per]<mission[mis].start && edge[per][mission[mis].idx])
 78     {
 79         int temp=fre[per];
 80         fre[per]=mission[mis].over;
 81         dfs(mis,per+1,now+1,val);
 82         fre[per]=temp;
 83     }
 84     dfs(mis,per+1,now,val);
 85 }
 86 
 87 void solve()
 88 {
 89     memset(fre,0,sizeof(fre));
 90     sort(mission,mission+m);
 91     dfs(0,0,0,0);
 92 }
 93 
 94 void print()
 95 {
 96     cout<<ans<<endl;
 97 }
 98 
 99 int main()
100 {
101     read();
102     solve();
103     print();
104 }

 

以上是关于BZOJ 1198 [HNOI2006]军机调度:dfs的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1193[HNOI2006]马步距离

BZOJ 1195: [HNOI2006]最短母串

BZOJ1196 [HNOI2006] 公路修建问题

bzoj 1196: [HNOI2006]公路修建问题 二分+并查集

BZOJ1191: [HNOI2006]超级英雄Hero

bzoj1193: [HNOI2006]马步距离