HNUCM 1353 wjw和ly的双人游戏 (回溯)

                                      1353: wjw和ly的双人游戏

 

时间限制: 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后,把搜索路径上所有的宝物数量累加

AC Code:

#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;
}

 

你可能感兴趣的:(HNUCM 1353 wjw和ly的双人游戏 (回溯))