CF510D Fox And Jumping
xiezheyuan · · 题解
简要题意
给出
n 张卡片,分别有l_i 和c_i 。在一条无限长的纸带上,你可以选择花c_i 的钱来购买卡片i ,从此以后可以向左或向右跳l_i 个单位。问你至少花多少元钱才能够跳到纸带上全部位置。若不可能,输出-1 。1 \leq n \leq 300,1 \leq l_i \leq 10^{9},1 \leq c_i \leq 10^{5}
思路
首先,如果我们可以选出一些个卡片
一开始,我的思路是能选择
7
15015 10010 6006 4290 2730 2310 1
1 1 1 1 1 1 10
答案应该是
然后我们考虑 DP,设
无法通过本题,考虑优化。发现这个动态转移方程很像三角形不等式
使用堆优化 Dijkstra 算法可以做到
代码
```cpp
#include <bits/stdc++.h>
#define int long long
#define gcd __gcd
using namespace std;
unordered_map<int, int> dis;
unordered_set<int> vis;
priority_queue<pair<int,int>, vector<pair<int,int> >, greater<pair<int,int> > > pq;
int n,l[305],c[305];
void dijkstra(){
pq.push({0,0});
dis[0]=0;
while(!pq.empty()){
int x = pq.top().second;
pq.pop();
if(x==1){
break;
}
if(vis.find(x) != vis.end()){
continue;
}
vis.insert(x);
for(int j=1;j<=n;j++){
int y = gcd(x,l[j]);
if(dis.find(y) == dis.end()){
dis[y] = INT_MAX;
}
if(dis[y]>dis[x]+c[j]){
dis[y]=dis[x]+c[j];
pq.push(make_pair(dis[y],y));
}
}
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>l[i];
}
for(int j=1;j<=n;j++){
cin>>c[j];
}
dijkstra();
if(dis.find(1)==dis.end()){
// Impossible
cout<<-1;
}
else{
cout<<dis[1];
}
return 0;
}
AC Record