​传送门​

D. Fox And Jumping_动态规划

题意:

给你n张卡片和初始坐标0,每张卡片都有一个D. Fox And Jumping_算法_02,每一张卡片可以跳到当前坐标加减D. Fox And Jumping_算法_02的位置同时每张卡片有对应的花费,每张卡片选取后可以任意次使用,问你想要跳到任意一个格子的最小花费。

思路:

首先解决一个问题:选取的卡片要满足何种条件才能够走到所有格子。这个问题不难解决,假设选取的卡片能跳的距离为D. Fox And Jumping_算法_04,当前位置为D. Fox And Jumping_#include_05那么选取的这k个卡片必须要能跳到pos+1或pos-1的位置,这样才能使得每一个位置都取到,即满足这样一个式子:D. Fox And Jumping_i++_06,由此可以推出D. Fox And Jumping_i++_07
当然,这题的难点显然不在这个结论上面,而在之后的处理上,我们设D. Fox And Jumping_i++_08表示当前能得到的gcd等于i的最小花费,每次用一张卡片的值去更新这些gcd即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long

struct node{
int l,c;
friend bool operator < (node a, node b)
{
return a.c > b.c;
}
}a[310];
map<int,int>dp;

int main()
{
map<int,int>::iterator iter;
int n;
cin>>n;
for(int i = 1; i <= n; i++)
{
cin>>a[i].l;
}
for(int i = 1; i <= n; i++)
{
cin>>a[i].c;
}
ll ans = 1e18;
sort(a+1,a+1+n);
int gcd = a[1].l;
for(int i = 1; i <= n; i++)
gcd = __gcd(gcd,a[i].l);
if(gcd > 1)
{
cout<<-1<<endl;
return 0;
}
for(int i = 1; i <= n; i++)
{
dp[a[i].l] = a[i].c;
}
for(int i = 1; i <= n; i++)
{
for(iter = dp.begin(); iter != dp.end(); iter++)
{
if(dp[__gcd(a[i].l,iter->first)] == 0)dp[__gcd(a[i].l,iter->first)] = a[i].c+iter->second;
else
dp[__gcd(a[i].l,iter->first)] = min(dp[__gcd(a[i].l,iter->first)], a[i].c+iter->second);
}
}
cout<<dp[1]<<endl;
}