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 }