列表

详情


NC20048. [HNOI2006]军机调度

描述

凯萨拥有一支由n个人组成的雇佣军,他们靠在威尼斯商行接任务过活。这支军队的成份比较复杂,不同的人往往具有不同的技能,有的人还拥有多项技能。威尼斯商行的任务也参差不齐,有的需要几个人合作完成,有的只需要一个人独立完成:有的很简单,不需要耗多少时间,因此报酬也较低,有的很有难度,需要多个人长期合作完成,因此报酬就高。完成这些任务的时间不会超过一个月。并且,一个人不能同时执行两项任务,也不能中途加入或者退出任务。但可以不执行任何任务。一项只需要n个人来完成的任务,如果执行该任务的人数p大于n,那么反而会得到更少的报酬,即原报酬的1/(p-n+1)。 凯萨是一位英明的领袖,他往往在每个月的月底召开军事会议,总结上个月的成果,发给大家报酬,并指派下个月的任务。 请问,凯萨应该怎样指派任务,才能使总报酬最高?总报酬为多少?

输入描述

一行包含两个正整数n,m。彼此用空格隔开,其中n〈10表示雇佣军的人数,m〈15表示下个月可选的任务数。
接下来的n行中,第i行(对应整个文件的第i+1行)的第一个整数小于等于表示编号为i的雇佣军可以执行的任务数,后面的整数是编号为i的雇佣军可以执行的所有任务的编号,这些整数之间用空格隔开。
最后的m行中,每行有四个整数b、e、p和r,彼此之间用空格隔开,其中第j行(对应整个文件的第n+j+1行)是编号为j的任务的描述:0 < b 〈 32表示该任务的开始日(这一天会被计入任务所需的时间中),0 < e〈32表示该任务的结束日(这一天也会被计入任务所需的时间中),p < 10表示该任务所需人数,0 < r 〈 100000表示该任务的报酬。

输出描述

第一行只有一个整数t,表示最多可获得的总报酬

示例1

输入:

3 5
2 1 4
2 2 4
3 3 4 5
2 20 1 100 
1 18 1 200 
3 28 1 800 
21 30 3 1500 
19 21 1 400

输出:

1800

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 4ms, 内存消耗: 488K, 提交时间: 2019-03-16 11:09:43

#include<cstdio>

#include<iostream>

#include<cstring>

#include<algorithm>

using namespace std;

int count(int x) {

int ans=0;

while (x) {

ans+=x&1;

x>>=1;

}

return ans;

}

#define maxn 35

int b[maxn],e[maxn],r[maxn],ans,n,m,p[maxn],s[maxn];

bool a[maxn][maxn],is[maxn][maxn];

int dfs(int x,int sum) {

if (sum>ans) ans=sum;

if (x==m+1) return 0;

dfs(x+1,sum);

int tot=0,s[maxn];

for (int i=1;i<=n;i++)

if (a[i][x]) {

bool flag=1;

for (int j=b[x];j<=e[x];j++)

if (is[i][j]) {flag=0;break;}

if (flag) s[++tot]=i;

}

if (tot<p[x]) return 0;

for (int i=1;i<(1<<tot);i++) {

if (count(i)!=p[x]) continue;

for (int j=1;j<=tot;j++) {

if ((1<<(j-1))&i){

int y=s[j];

for (int k=b[x];k<=e[x];k++) is[y][k]=1;

}

}

dfs(x+1,sum+r[x]);

for (int j=1;j<=tot;j++) {

if ((1<<(j-1))&i){

int y=s[j];

for (int k=b[x];k<=e[x];k++) {is[y][k]=0;}

}

}

}

return 0;

}

int main(){

scanf("%d%d",&n,&m);

for (int i=1;i<=n;i++) {

int x;

scanf("%d",&x);

for (int j=1;j<=x;j++) {

int y;

scanf("%d",&y);

a[i][y]=1;

}

}

for (int i=1;i<=m;i++) {

scanf("%d%d%d%d",b+i,e+i,p+i,r+i);

}

dfs(1,0);

printf("%d",ans);

return 0;

}

上一题