题目描述
你是一名记者,现在要求你去采访n 个国家的领导人。采访每一个国家的领导人需要消耗你的时间为t[i],但你可以收获价值为v[i]的信息,然后就能写成报道……
然而尴尬的是,有一些国家之间的关系属于敌对关系,因此如果一个国家的领导人知道你采访了他的敌对国家领导人,那么他就会拒绝你的采访。总之,你采访的国家中,任意选出一对国家都不能构成敌对关系,你才能够完成你的采访,否则某些部分就要落空。
你的Boss他给了你一个时间限制T,如果你在时间限制内没有完成采访任务,你就会被炒鱿鱼。当然,他希望你在时间限制T 内完成的采访累计起来的价值总和最大。
输入
第一行有三个数,第一个数为时间限制T,第二个数为国家数量n,第三个数为国家之间的敌对组数m。
接下来n 行,每行两个数,第一个数为t[i],第二个数为v[i]。
接下来m 行,每行有m[i]+1 个数,首先输入m[i],表示这一组中一共有多少国家是敌对关系,之后输入m[i]个数,表示这m[i]个国家两两之间为敌对关系(一组敌对关系的国家中,每两个国家都构成敌对关系,比如这一组是1,3,4,那么1 和3,1 和4,3 和4 都构成敌对关系),若m[i] = 1,那么这个国家与其他国家都不构成敌对关系。
输出
一个整数,表示最大价值V。
样例输入
10 5 2
5 10
7 9
6 3
1 13
8 1
3 1 3 4
2 2 5
样例输出
22
数据范围限制
60%的数据:m=1;
100%的数据:0≤T≤50000,0≤n≤500,1≤m≤10,n=∑m[i],即m[1]+m[2]+…=n,且敌对关系中每个国家编号只会出现一次。
解题思路
类似背包
设
f
[
i
]
[
k
]
f[i][k]
f[i][k]表示第
i
i
i圈敌对关系时间花费为
k
k
k得到最大的价值
(
e
n
e
m
y
[
]
[
]
enemy[][]
enemy[][]存储敌对关系,
j
j
j用来枚举关系圈里的国家)
f
[
i
]
[
k
]
=
m
a
x
f[i][k]=max
f[i][k]=max{
f
[
i
−
1
]
[
k
−
w
[
e
n
e
m
y
[
i
]
[
j
]
]
]
+
v
[
e
n
e
m
y
[
i
]
[
j
]
]
f[i-1][k-w[enemy[i][j]]]+v[enemy[i][j]]
f[i−1][k−w[enemy[i][j]]]+v[enemy[i][j]]}
(
1
<
=
i
<
=
m
,
1
<
=
j
<
=
e
n
e
m
y
[
i
]
[
0
]
,
w
[
e
n
e
m
y
[
i
]
[
j
]
]
<
=
k
<
=
t
i
m
e
)
(1<=i<=m,1<=j<=enemy[i][0],w[enemy[i][j]]<=k<=time)
(1<=i<=m,1<=j<=enemy[i][0],w[enemy[i][j]]<=k<=time)
最后输出 f [ m ] [ t i m e ] f[m][time] f[m][time]
注:不要尝试一维,一维行不通,因为这题比较bt
#include<iostream>
#include<cstdio>
using namespace std;
int ti,n,m,w[600],v[600],enemy[20][600],f[600][50100];
int main(){
freopen("interview.in","r",stdin);
freopen("interview.out","w",stdout);
scanf("%d%d%d",&ti,&n,&m);
for(int i=1;i<=n;i++)
scanf("%d%d",&w[i],&v[i]);
for(int i=1;i<=m;i++){
scanf("%d",&enemy[i][0]);
for(int j=1;j<=enemy[i][0];j++)
scanf("%d",&enemy[i][j]);
}
for(int i=1;i<=m;i++){
for(int j=1;j<=ti;j++)
f[i][j]=f[i-1][j];
for(int j=1;j<=enemy[i][0];j++)
for(int k=ti;k>=w[enemy[i][j]];k--)
f[i][k]=max(f[i][k],f[i-1][k-w[enemy[i][j]]]+v[enemy[i][j]]);
}
printf("%d",f[m][ti]);
}