时间限制: 1 内存限制: 128 MB
题目描述
wjw和ly最近买了一个switch玩,switch上有个游戏,具体过程可以简化成在一张地图上,有N个城堡,每个城堡都有宝物,每局游戏中允许他们攻破M个城堡并且获得奖励,但是由于地图的限制,有些城堡不能直接攻破,要攻破这些城堡必须先攻破其他特定的城堡,所以你可以帮ly和wjw计算出怎么攻破城堡能获得最多的宝物吗?
输入
每组测试数据包含2个整数,N,M(1 <= M <= N <= 10);
在接下来的N行里,每行包含2个整数a,b.
在第 i 行,a 代表要攻克第 i 个城堡必须先攻克第 a 个城堡,如果 a = 0 则代表可以直接攻克第 i 个城堡。
b 代表第 i 个城堡的宝物数量, b >= 0。
当N = 0, M = 0输入结束。
输出
对于每组数据,输出一个整数,表示ly和wjw能够获得的最多宝物的数量。
样例输入
3 2
0 1
0 2
0 3
7 4
2 2
0 1
0 4
2 1
7 1
7 6
2 2
0 0
样例输出
5
13
很久以前没写出来的一道搜索题
搜索思路:从物品1开始向物品n搜索,每次有取或不取两种情况。
每次搜索数量达到m后,把搜索路径上所有的宝物数量累加
#include
#include
#include
#include
#include
#include
#define mod 1000000007
#define INF 0x3f3f3f3f
#define BUG printf("-------BUG------\n")
static const double pi = acos(-1);
using namespace std;
typedef long long ll;
int a[15], b[15];
bool vis[15];
int n, m;
int res;
int getval(){ //获取每次搜索路径上的所有宝物
int v = 0, k = 0;
for(int i = 1; i <= n; i++){
if(vis[i]){
if(a[i] == 0 || vis[a[i]]){ //城堡可以直接取或先决城堡已经攻破
v += b[i];
k++;
}
}
}
if(k == m) return v;
return 0;
}
void dfs(int s, int sum){
if(sum == m) {
res = max(res, getval());
return;
}
if(sum > m || s > n) return;
vis[s] = true; //标记
dfs(s + 1, sum + 1); //取当前宝物
vis[s] = false; //回溯
dfs(s + 1, sum); //不取当前宝物
}
int main(){
while(scanf("%d%d", &n, &m) != EOF){
if(n == 0 && m == 0) break;
memset(vis, false, sizeof(vis));
for(int i = 1; i <= n; i++){
scanf("%d%d", &a[i], &b[i]);
}
res = -INF;
dfs(1, 0);
printf("%d\n", res);
}
return 0;
}