导游2

问题 B: 导游2

时间限制: 1 Sec  内存限制: 128 MB
提交: 84  解决: 52
[提交][状态][讨论版]

题目描述

宁波市的中小学生们在镇海中学参加程序设计比赛之余,热情的主办方邀请同学们参观镇海中学内的各处景点,已知镇海中学内共有n处景点。现在有n位该校的学生志愿承担导游和讲解任务。每个学生志愿者对各个景点的熟悉程度是不同的,如何将n位导游分配至n处景点,使得总的熟悉程度最大呢?要求每个景点处都有一个学生导游。

输入

有若干行:

第一行只有一个正整数n,表示有n个景点和n个学生导游。

第二行至第n+1行共n行,每行有n个以空格分隔的正整数。第i+1行的第j个数k(1≤k≤1000),表示第i个学生导游对景点j的熟悉程度为k。

输出

只有一行,该行只有一个正整数,表示求得的熟悉程度之和的最大值。

样例输入

3
10 6 8
9 2 3
1 7 2

样例输出

24

提示


【样例说明】


第 10.5pt">1个学生负责第3个景点,第 10.5pt">2个学生负责第1个景点,第 10.5pt">3个学生负责第2个景点时,熟悉程度总和为24,达到最大值。 10.5pt">


【数据限制】


100%的数据,1≤n≤17。

如果熟悉dp的大牛应该不难发现这也是一道状态压缩类的dp,压缩什么状态呢,当然是n,数据范围小,可以用1表示哪个景点已经有人了,0表示还没有人。这样一个转移思路就出来了,用记忆化实现,一个状态中比如1000011100 枚举每一个二进制位为1,表示第4个学生去哪个景点,这样每次转移,复杂度为O(n*(1<<n)) 大约10 million 左右
 
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<string>
 
using namespace std;
const int MAXN=19;
 
int a[MAXN][MAXN],dp[(1<<17)+7];
int n;
 
void init()
{
    memset(dp,-1,sizeof(dp));
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
            scanf("%d",&a[i][j]);
}
void dfs(int sta,int num)
{
    if (num==0)
    {
        dp[sta]=0;
        return;
    }
    if (dp[sta]!=-1) return;
     
    int res=0;
    for (int i=0;i<n;i++)
    {
        int x=sta;
        if ((1<<i)&sta)
        {
            x=x^(1<<i);
            dfs(x,num-1);
            res=max(res,dp[x]+a[num][i+1]);
        }
    }
    dp[sta]=res;
}
int main()
{
    scanf("%d",&n);
    init();
    dfs((1<<n)-1,n);
    printf("%d",dp[((1<<n)-1)]);
}
View Code
原文地址:https://www.cnblogs.com/fengzhiyuan/p/6894568.html