售货员的难题

来源:互联网 发布:知柏地黄丸一般吃多久 编辑:程序博客网 时间:2024/04/29 22:30

题目桑
虽然设定里n是到40可是很明显40是带不动的
初步估计40!
求最短路径又很明显不是图论类的于是想到

贪心 dp bfs

尽管老师说搜索是可以的然而我是个搜索废
滚去写dp
一开始按大白上面的那道题的思路走的 感觉比较不顺手
可自己也码不动(太弱啦
考虑为什么不在自己的状态内进行转移(可是还是不会打
于是很怂逼去看了题解
嗯这就是我要的(滑板鞋

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<string>using namespace std;int w[30][30];int len[30];int s[1100000][20];int main(){    freopen ("shou.in","r",stdin);    freopen ("shou.out","w",stdout);    int n;    scanf ("%d",&n);    int x;    //初始化 毕竟后面求最小值    memset(w,0x3f,sizeof(w));    memset(s,0x3f,sizeof(s));    for (int i=1;i<=n;++i)        for (int j=1;j<=n;++j){            scanf("%d",&x);            if (x) w[i][j]=x;        }    s[1][1]=0;    x=(1<<n)-1;//最终状态    for (int i=3;i<=x;i+=2)//枚举状态        for (int v=1;v<=n;++v){            if (i&(1<<v-1)){                for (int j=2;j<=n;++j)//枚举两个状态中的点                    if (v!=j&&(i&(1<<j-1))){                       int k=i&(~(1<<j-1));                       //在后者还未被访问的情况下转移                        s[i][j]=min(s[i][j],s[k][v]+w[v][j]);                    }            }        }           int ans=100000000;    for (int i=1;i<=n;++i) ans=min(ans,s[x][i]+w[i][1]);    //走完全程回到起点    if (ans==100000000) cout<<-1;    else cout<<ans;    return 0;  }

这类题目一开始看到肯定会走弯路
估计抓破头皮也只能勉强打个疯狂优化的爆搜
所以还是要多锻炼思维啊少年
很多题目的最优解法往往是和题意不怎么直接相关的qwq

0 0