HDU-4571-spfa,记忆化搜索,背包,DP

来源:互联网 发布:tough cookie.js 编辑:程序博客网 时间:2024/05/19 18:13

https://cn.vjudge.net/contest/165541#problem/G
G题可以用记忆化搜索。
大致题意就是给一些景点,有边权(路上的话费)和点权(游览的时间),和每个景点的满意度,问你最大满意度的方案。
因为可以有的点经过而不访问,并且景点之间可能有好多路。
所以先用floyd来确定任意两点的最小距离
(这样就包含了pass某些点的情况)
然后用记忆化搜索,用t和顶点的标号来限制。
背包也可以写,还没怎么搞明白。。
还有用floyd进行的DP
或者spfa下进行的DP
注意:在进行spfa的时候一定不要影响最基本的松弛条件。
用spfa求的最长路(
需要注意的是越过某些景点的操作在floyd的过程中也进行过了,所以只要老老实实的spfa就行。

还要记录当前话费的状态,防止出现t的大小超出限制。
很好的spfa应用。
还要加两个点。
/*用spfa的方法。
注意 要建立一个超级源点和 超级汇点。
正常的spfa只有边权。
如果还有点权,那么只要遍历的时候加上的时候就行了。
但对于第一个点,是不能进行取舍的。因为他是肯定要入栈的
所以要加一个超级源点记录那些visit第一个点的方法
第二就是搞一个超级汇点,目的是为了终点的判断。
然后在进行spfa的同时进行dp
注意先用floyd走一遍,然后在进行最短路
*/
spfa

#include <iostream>#include <cstdlib>#include <cstdio>#include <cstring>#include <queue>#include <stack>#include <string>using namespace std;const int maxn=300;int s,e;int T;int m,n;int cost[maxn];int val[maxn];int g[maxn][maxn];void floyd(){    for(int i=0;i<m+2;i++) g[i][i]=0;     for(int k=0;k<m;k++)       for(int i=0;i<m;i++)         for(int j=0;j<m;j++)         g[i][j]=min(g[i][k]+g[k][j],g[i][j]);}int spfa(int first,int second){ //int d[maxn];    bool vis[maxn][maxn];    int dp[maxn][maxn];    memset(dp,0,sizeof(dp));    int ans=-1;    memset(vis,false,sizeof(vis));    queue<int>q;    queue<int>qq;    q.push(first);    qq.push(0);    //d[first]=0;    vis[first][0]=true;    while(!q.empty())    {   int u=q.front();q.pop();        int uct=qq.front();qq.pop();        vis[u][uct]=false;        if(u==second)            ans=max(ans,dp[u][uct]);            for(int i=0;i<m;i++)        {   if((i==u)||(val[u]>=val[i]&&i!=second))continue;            int costing=uct+cost[i]+g[u][i];            if((costing<=T)&&(dp[i][costing]<dp[u][uct]+val[i]))                //if ((dp[i][costing] < dp[u][uct] + val[i])&&(costing<=T))            {    dp[i][costing]=dp[u][uct]+val[i];                 if(!vis[i][costing])                 {   //vis[i][costing]=true;                     q.push(i);                     qq.push(costing);                     vis[i][costing]=true;                 }            }        }        }    return ans;}int main(){    int tt;   int a,b,c;        cin>>tt;   for(int sss=1;sss<=tt;sss++){   memset(g,0x3f,sizeof(g));    cin>>m>>n>>T>>s>>e;   for(int i=0;i<m;i++)      cin>>cost[i];   for(int i=0;i<m;i++)       cin>>val[i];    for(int i=0;i<n;i++)         {cin>>a>>b>>c;          if(c<g[a][b])          {  g[a][b]=c;             g[b][a]=c;          }         }        floyd();        int ss=m;        int tt=m+1;        cost[ss]=cost[tt]=0;        val[ss]=val[tt]=0;        for(int i=0;i<m;i++)        if(g[s][i]!=0x3f3f3f3f)        g[ss][i]=g[s][i];        //g[ss][tt]=g[s][e];        for(int i=0;i<m;i++)            if(g[i][e]!=0x3f3f3f3f)            g[i][tt]=g[i][e];            g[ss][tt]=g[s][e];            m+=2;            printf("Case #%d:\n",sss);        cout<<spfa(ss,tt)<<endl;}    return 0;}

记忆化搜索

#include<iostream>#include<cstdio>#include<list>#include<algorithm>#include<cstring>#include<string>#include<queue>#include<stack>#include<map>#include<vector>#include<cmath>#include<memory.h>#include<set>using namespace std;const int maxn=105;const int INF=0x3f3f3f3f;int dp[maxn][maxn][3*maxn];int cost[maxn];int val[maxn];int a[maxn][maxn];int m,n;int s,e;int T;int floyd(){  for(int i=0;i<m;i++) a[i][i]=0;    for(int k=0;k<m;k++)     for(int i=0;i<m;i++)        for(int j=0;j<m;j++)           a[i][j]=min(a[i][k]+a[k][j],a[i][j]);           return 0;}void init(){memset(dp,-1,sizeof(dp)); memset(a,0x3f,sizeof(a)); //for(int i=0;i<m;i++)    //a[i][i]=0;}int dfs(int x,int value,int t){ if(a[x][e]>t) return -INF;  if(dp[x][value][t]!=-1) return dp[x][value][t];   int ans=0;   for(int i=0;i<m;i++)   {       if(a[x][i]!=INF&&value>=val[i]) continue;       ans=max(ans,dfs(i,val[i],t-cost[i]-a[x][i])+val[i]);   }    dp[x][value][t]=ans;    return ans;}int main(){   int ttt;   int a1,b,c;    cin>>ttt;   for(int ss=1;ss<=ttt;ss++){   init();    cin>>m>>n>>T>>s>>e;     for(int i=0;i<m;i++)cin>>cost[i];     for(int i=0;i<m;i++)cin>>val[i];     for(int i=0;i<n;i++)  {   cin>>a1>>b>>c;      if(c<a[a1][b])      {a[a1][b]=c;       a[b][a1]=c;      }  }  printf("Case #%d:\n",ss);  floyd();  printf("%d\n",dfs(s,0,T));}    return 0;}
原创粉丝点击