牛客训练五:炫酷路途(c++与dp)
题目链接:传送门
思路:每隔2^i(0<=i<=INF)就有一条路径,所以可以将从头到尾的路线视为一个有向图,
将ai,bi以此输入,然后将路径从小到大排序,不断更新路径。
__builtin_popcount (unsigned u)函数可以以O(1)的复杂度计算u的二进制中的数字1的个数。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int INF = 999999; int a[50],b[50],dis[50]; vector <int> vc; int main(void) { int n,m,i,j,p,k; while(~scanf("%d%d",&n,&k)){ vc.clear(); for(i=0;i<k;i++){ scanf("%d%d",&a[i],&b[i]); if(a[i]>b[i]) swap(a[i],b[i]); vc.push_back(a[i]); vc.push_back(b[i]); } vc.push_back(1);vc.push_back(n); sort(vc.begin(),vc.end()); vc.erase(unique(vc.begin(),vc.end()),vc.end()); memset(dis,INF,sizeof(dis)); dis[0]=0; int len=vc.size(); for(i=0;i<len;i++) for(j=i+1;j<len;j++){ for(p=0;p<len;p++) if(vc[i]==a[p]&&vc[j]==b[p]){ dis[j]=min(dis[i]+1,dis[j]); } dis[j]=min(dis[j],dis[i]+__builtin_popcount(vc[j]-vc[i])); } printf("%d\n",dis[len-1]); } return 0; }