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

    xiaoxiao2021-03-25  76

    一道很有意思的题目

    阿明是一名推销员,他奉命到螺丝街推销他们公司的产品。螺丝街是一条死胡同,出口与入 口是同一个,街道的一侧是围墙,另一侧是住户。螺丝街一共有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; }

    还算易懂的代码

    转载请注明原文地址: https://ju.6miu.com/read-22693.html

    最新回复(0)