Light OJ 1281
来源:互联网 发布:gta5美女角色捏脸数据 编辑:程序博客网 时间:2024/06/14 05:36
【题意】大意就是一个人要从0点走到n-1点,路中有些点有商店可以买礼物,所以这个人想买多点礼物,但是又要尽快的走到n-1点,这两者之间呢,礼物的多少优先,其次是路程长度。
【分析】16个点显然是可以状压的,dp[sta][i]表示当前遍历的点的状态sta停留在shop[i]的最短路的估计值。这样状态首先是可以表示完全的,转移就显然很简单了。先预处理出每个商店到其他点的最短路径,以便后面的状态转移的需要。
【关键问题】最短路+TSP。
【最短路】这里最短路必须对n个点分别跑一遍,500个点,果断堆优化Dijstra!
【TSP】状压典型例题!dp[state][i]表示在i点,状态为state的最优答案。
【AC代码】一个巨长的ac代码,参考了别人的思路,花了两天写出并调试AC,还是太弱了~
#include <stdio.h>#include <vector>#include <queue>#include <string.h>#include <iostream>#include <algorithm>#include <assert.h>using namespace std;const int maxn = 502;const int maxm = 16;const int inf = 0x3f3f3f3f;struct edge{ int u,v,w; edge(){} edge(int u,int v,int w):u(u),v(v),w(w){}};struct node{ int u,dis; node(){} node(int u,int dis):u(u),dis(dis){} bool operator<(const node &x)const { return dis>x.dis; }};vector<edge>G[maxn];int d[maxn][maxn];int dp[1<<maxm][maxm];int a[maxn];int vis[maxn];int n,m,t;void Heap_Dijstra(int s){ node cur; for(int i=0;i<=n;i++)d[s][i]=inf; memset(vis,false,sizeof(vis)); d[s][s]=0; priority_queue<node>que; que.push(node(s,0)); while(!que.empty()) { cur=que.top(); que.pop(); int u=cur.u; if(vis[u])continue; vis[u]=true; for(int i=0;i<(int)G[u].size();i++) { edge temp=G[u][i]; int v=temp.v; if(d[s][v]>cur.dis+temp.w) { d[s][v]=cur.dis+temp.w; que.push(node(v,d[s][v])); } } }}int get_num(int x){ int ans=0; while(x) { if(x&1)ans++; x>>=1; } return ans;}int main(){ int T,cas=1; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&t); for(int i=0;i<=n;i++)G[i].clear(); for(int i=0;i<t;i++) { scanf("%d",&a[i]);//where shop is ! } for(int i=0;i<m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); G[u].push_back(edge(u,v,w)); } for(int i=0;i<n;i++) { Heap_Dijstra(i); } //TSP. for(int s=0;s<(1<<t);s++) { for(int i=0;i<t;i++) { dp[s][i]=inf; if(!(s&(1<<i)))continue; if(s==(1<<i)){ dp[s][i] = d[0][a[i]]; continue; } for(int j=0;j<t;j++) { if((s&(1<<j))&&(i!=j)) { if(dp[s^(1<<i)][j]==inf)continue; if(d[a[j]][a[i]]==inf)continue; dp[s][i]=min(dp[s^(1<<i)][j]+d[a[j]][a[i]],dp[s][i]); } } } } //Find answer ! int ans=inf,sum=0; for(int s=0;s<(1<<t);s++) { for(int i=0;i<t;i++) { if(dp[s][i]==inf||d[a[i]][n-1]==inf)continue; int temp=get_num(s); if(sum<temp||(sum==temp&&ans>dp[s][i]+d[a[i]][n-1])) { sum = temp; ans = dp[s][i]+d[a[i]][n-1]; } } } printf("Case %d: ",cas++); if(sum==0) puts("Impossible"); else printf("%d %d\n",sum,ans); } return 0;}
1 0
- Light OJ 1281
- light oj
- light oj
- Light OJ
- Light OJ
- Light OJ 1000
- Light OJ 1001
- Light OJ 1008
- Light OJ 1022
- Light OJ 1015
- Light OJ 1042
- light oj 1128
- Light OJ 1055 BFS
- Light OJ Beginners Problems
- Light OJ Basic Geometry
- Light OJ Basic Math
- light oj 1124
- Light OJ 1012
- HDU 1160 FatMouse's Speed 最长上升子序列,重拾DP
- C++/MFC CString,string,char*转换
- 使用Autolayout xib实现动态高度的TableViewCell
- OC与JS的简单交互
- ios牛人博客
- Light OJ 1281
- 动态规划
- 数据库创建--创建表(课堂笔记)
- vi/vim编辑器必知必会
- IOS中静态库的使用
- Matlab信号添加噪声及信噪比SNR的计算
- Redis安装和配置
- Ruby On Rails--Active Record Migrations(数据库迁移)
- Java泛型