POJ 2088 Long Night of Museums

Description

The city of Vienna is called the "City of Culture" because (among other things) there are more than 100 museums in the city. As a consequence, it is very difficult (and very expensive) to visit all of them no matter how long you stay in the city. Fortunately, there is a special night, called the "Long Night of Museums", when you can visit many museums with just one ticket, from 6:00 pm to 1:00 am of the next day.
Nevertheless, it is impossible to visit every museum of the city for two main reasons. First, some museums in Vienna don't get involved into this event because they close at 5:00 pm. Second, there is not enough time in 7 hours to go to every museum, watch ALL their insides (otherwise, it would be a waste of time), and then go to the others.
Given the number of museums participating in the Long Night of Museums, the time needed to watch the insides of each museum, and the time that it will take to get from each museum to the others, you have to find the best tour to visit as many museums as you can during the Long Night of Museums.

Input

The input contains several test cases. The first line of a test case contains one integer N, which indicates the number of museums participating in the event (1 <= N <= 20). Each museum has a unique identification number ranging from 1 to N. The second line of a test case contains N integers indicating the time, in minutes, needed to visit each museum, from 1 to N. Then there are N lines describing the times to go from one museum to every other. The i-th line contains N integers Mk (1 <= k <= N) representing the time, in minutes, to go from museum i to museum k. You may assume that the i-th integer in the i-th line is equal to zero. The end of input is indicated by N = 0

Output

For each test case in the input, your program must produce one line containing the maximum number of museums that can be visited during the Long Night of Museums.

Sample Input

2
500 500
0 120
200 0
2
220 220
0 30
20 0
2
150 150
0 120
200 0
0

Sample Output

0
1
2

Hint

You must find to try your best to visit as many DIFFERENT museums as you can during the Long Night of Museums.       

解题思路:这题用状压DP超时,原因就是计算了一些无用的状态或者当前状态已经能够得出最优解,却没有及时跳出,看了网上某人的代码,便是利用dfs+剪枝。
<pre name="code" class="cpp">#include <ctime>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <numeric>
#include <algorithm>
#include <functional>
using namespace std;
const int maxn = 25;
const int inf  = 0x3f3f3f3f;
int g[maxn][maxn], cost[maxn];
int dp[(1<<20)+10];
int n;
int ans;

void floyd() {
    for(int k = 0; k < n; ++k) {
        for(int i = 0; i < n; ++i) {
            if(i == k) continue;
            for(int j = 0; j < n; ++j) {
                if(j == k || i == j) continue;
                g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
            }
        }
    }
    return ;
}

void dfs(int p, int c, int s) {
    if(ans == n) return ;
    if(ans < c) ans = c;
    if(dp[s] <= 0) return ;
    for(int i = 0; i < n; ++i) {
        if(!(s&(1<<i))) {
            if(dp[s] - g[p][i] - cost[i] < 0) continue;
            if(dp[s|(1<<i)] < dp[s] - g[p][i] - cost[i]) {
                dp[s|(1<<i)] = dp[s] - g[p][i] - cost[i];
                dfs(i, c + 1, s|(1<<i));
            }
        }
    }
    return ;
}


int main() {

    //freopen("aa.in", "r", stdin);
    while(scanf("%d", &n) && n) {
        for(int i = 0; i < n; ++i) {
            scanf("%d", &cost[i]);
        }
        for(int i = 0; i < n; ++i) {
            for(int j = 0; j < n; ++j) {
                scanf("%d", &g[i][j]);
            }
        }
        floyd();
        memset(dp, -1, sizeof(dp));
        ans = 0;
        for(int i = 0; i < n; ++i) {
            if(cost[i] <= 420) {
                dp[1<<i] = 420 - cost[i];
                dfs(i, 1, 1<<i);
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

来说一下这份代码中dfs的两个关键点:(1)如果当前状态已经得出能够拜访完所有的节点此时我们应该及时return掉,否则会产生超时,因为后序的状态没有计算的必要性了,结果肯定为n。(2) dp[s|(1<<i)] < dp[s] - g[p][i] - cost[i]这句代码中的<换成<=号的话也会超时,一开始不怎么理解,认为当前节点集合在最优值相同但是最后访问的那个节点不同时,接下来的状态转移可能导致最优结果不相同,但是改成<=号会超时。可能是因为图为无向图,如果s集合的最优方案为i,j分别为起始点和终止点,再加上我们是枚举从每个顶点出发进行dfs的,因此那样的话会重复计算很多状态,导致超时???
 
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值