洛谷P2672 售货员题解 (记忆化搜索,状压DP)

来源:互联网 发布:淘宝电子商务模式分析 编辑:程序博客网 时间:2024/05/22 07:04

一道很有意思的题目

阿明是一名推销员,他奉命到螺丝街推销他们公司的产品。螺丝街是一条死胡同,出口与入 口是同一个,街道的一侧是围墙,另一侧是住户。螺丝街一共有N家住户,第i家住户到入口 的距离为Si米。由于同一栋房子里可以有多家住户,所以可能有多家住户与入口的距离相等。 阿明会从入口进入,依次向螺丝街的X家住户推销产品,然后再原路走出去。 阿明每走1米就会积累1点疲劳值,向第i家住户推销产品会积累Ai点疲劳值。阿明是工作狂, 他想知道,对于不同的X,在不走多余的路的前提下,他最多可以积累多少点疲劳值。
【输入格式】 输入文件名为salesman.in。 第一行有一个正整数N,表示螺丝街住户的数量。 接下来的一行有N个正整数,其中第i个整数Si表示第i家住户到入口的距离。数据保证 S1≤S2≤…≤Sn<108。 接下来的一行有N个正整数,其中第i个整数Ai表示向第i户住户推销产品会积累的疲劳值。 数据保证Ai<103。
【输出格式】 输出文件名为salesman.out。 输出 N 行,每行一个正整数,第 i 行整数表示当 X=i 时,阿明最多积累的疲劳值。

记忆化搜索加上状压DP。
上代码吧。。

#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;int f[15][1<<15];int r[(1<<15)+1];int w[15][15];int inf=(1e9)+7;int min(int x,int y){    if(x<=y) return x;    else return y;}int dfs(int u,int state){    //printf("%d %d\n",u,state);    if(f[u][state]!=-1) return f[u][state];    int rstate=state&(~(1<<u)); // vis[u] = true;    if(rstate==0) return f[u][state]=w[u][0];    int ans=inf;    while(rstate)     {        int p=(rstate)&(-rstate);        int v=r[p];        ans=min(ans,dfs(v,state&(~(1<<u)))+w[u][v]);         rstate-=p;    }    return f[u][state]=ans;}int main() {    freopen("salesman.in","r",stdin);    freopen("salesman.out","w",stdout);    int n;    scanf("%d",&n);    for (int i=0;i<=n;i++)    for (int j=0;j<n;j++)     scanf("%d",&w[i][j]);    for (int i=0;i<= 15;i++)    r[1<<i]=i;    memset(f,-1,sizeof(f));    int lim=(1<<n)-1;    printf("%d\n",dfs(0,lim));    return 0;}

还算易懂的代码

2 0