poj 3411 搜索+剪枝

来源:互联网 发布:怎样判断网络通不通 编辑:程序博客网 时间:2024/05/21 15:44

记忆化搜索:s[status][cur] 记录在当前状态下,此刻位于cur点,到目的地所要的花费,由于一旦状态和位置确定,这个值是一定的
二进制状态表示:注意到n,m都比较小,由此启发
有一个剪枝:防止impossible时与目的地不连通而产生无限循环,
有m条边,对于每条边,最多存放在m个环中,故为m*m

 

 

#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <vector>using namespace std;#define INF 10000000struct pp{int b,c,p,r;pp(){b=c=p=r=0;}pp(int _b,int _c,int _p,int _r){b=_b;c=_c;p=_p;r=_r;}};int n,m;int vis[2500][11];int s[2500][11];vector<pp>vec[100];int min(int aa,int bb){return aa<bb?aa:bb;}int ans;int renew(int status,int pos){return status|(1<<(pos-1));}bool isvis(int status ,int pos){return status&(1<<(pos-1));}int dfs(int cur,int status,int cost){if(s[status][cur]!=-1)return s[status][cur];if(cur==n)return 0;vis[status][cur]++;int tt,sstatus,temp;int ret=INF;if(vis[status][cur]>m*m)return INF;for(int i=0;i<vec[cur].size();++i){tt=INF;sstatus=renew(status,vec[cur][i].b);if(isvis(status,vec[cur][i].c))tt=dfs(vec[cur][i].b,sstatus,cost+vec[cur][i].p);temp=dfs(vec[cur][i].b,sstatus,cost+vec[cur][i].r);if(tt<temp)s[sstatus][vec[cur][i].b]=tt;else s[sstatus][vec[cur][i].b]=temp;if(tt+vec[cur][i].p<temp+vec[cur][i].r)ret=min(ret,tt+vec[cur][i].p);else ret=min(ret,temp+vec[cur][i].r);}return ret;}int main (){//freopen("aa.txt","r",stdin);//freopen("bb.txt","w",stdout);while(scanf("%d%d",&n,&m)!=EOF){for(int i=0;i<=n;++i)vec[i].clear();int a,b,c,p,r;for(int i=1;i<=m;++i){scanf("%d%d%d%d%d",&a,&b,&c,&p,&r);vec[a].push_back(pp(b,c,p,r));}ans=INF;memset(vis,0,sizeof(vis));memset(s,-1,sizeof(s));ans=dfs(1,1,0);if(ans>=INF)printf("impossible\n");elseprintf("%d\n",ans);}//system("pause");return 0;}

 


后来研究出更简洁的代码,因为参考了网上的代码,但发现这是错的

网上有人用了个强剪枝 vis[cur]>3 ,即不允许在同一条1-n的走的路径上走过一个环3次,

但下面这组数据程序就过不了,虽然在poj上过了

6 9
1 2 1 1 1
2 1 2 1 1
1 3 2 1 100
3 1 3 1 1
1 4 3 1 100
4 1 4 1 1
1 5 4 1 100
5 1 5 1 1
1 6 5 1 100

所以应该 vis[cur]>m*m

#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <vector>using namespace std;#define INF 10000000struct pp{int b,c,p,r;pp(){b=c=p=r=0;}pp(int _b,int _c,int _p,int _r){b=_b;c=_c;p=_p;r=_r;}};int n,m,ans,vis[15];bool flag;vector<pp>vec[100];int min(int aa,int bb){return aa<bb?aa:bb;}void dfs(int cur,int cost){if(cost>=ans||vis[cur]>m*m)return ;if(cur==n){flag=true;ans=cost;return;}vis[cur]++;for(int i=0;i<vec[cur].size();++i){if(vis[vec[cur][i].c])dfs(vec[cur][i].b,cost+vec[cur][i].p);dfs(vec[cur][i].b,cost+vec[cur][i].r);}vis[cur]--;}int main (){//freopen("aa.txt","r",stdin);//freopen("bb.txt","w",stdout);while(scanf("%d%d",&n,&m)!=EOF){for(int i=0;i<=n;++i)vec[i].clear();int a,b,c,p,r;for(int i=1;i<=m;++i){scanf("%d%d%d%d%d",&a,&b,&c,&p,&r);vec[a].push_back(pp(b,c,p,r));}ans=INF;flag=false;memset(vis,0,sizeof(vis));dfs(1,0);if(ans>=INF)printf("impossible\n");elseprintf("%d\n",ans);}system("pause");return 0;}


 

 

原创粉丝点击