D. Fox And Jumping
原创
©著作权归作者所有:来自51CTO博客作者wx636883f8ce969的原创作品,请联系作者获取转载授权,否则将追究法律责任
传送门
题意:
给你n张卡片和初始坐标0,每张卡片都有一个,每一张卡片可以跳到当前坐标加减的位置同时每张卡片有对应的花费,每张卡片选取后可以任意次使用,问你想要跳到任意一个格子的最小花费。
思路:
首先解决一个问题:选取的卡片要满足何种条件才能够走到所有格子。这个问题不难解决,假设选取的卡片能跳的距离为,当前位置为那么选取的这k个卡片必须要能跳到pos+1或pos-1的位置,这样才能使得每一个位置都取到,即满足这样一个式子:,由此可以推出。
当然,这题的难点显然不在这个结论上面,而在之后的处理上,我们设表示当前能得到的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;
}