题目链接:http://codeforces.com/problemset/problem/510/D
题意:有N张卡牌,每张卡牌有属性l和cost,选择一张卡牌后需要花费cost,可以走l距离(卡牌选择后可以多次使用),问如何花费最小可以走到任何地方
思路:要走到任何地方也就是要卡牌组合成1(如选择l=3和l=2的2张卡牌),这里有一个数学定理,gcd(a,b)=1则代表可以用a和b组合出任意的数(如果不等于1大概就是表示可以组成的最小的数),通过枚举所有卡牌更新可以组合出的所有数的最小值就可以(看了别人的代码用了map来写dp很简介……学习了下)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#define maxn 330
#define LL long long
using namespace std;
map <LL,LL> mp;
LL cost[maxn],val[maxn];
LL gcd(LL a,LL b)
{
if (a<b) swap(a,b);
if (b!=0) return gcd(b,a%b);
else return a;
}
int main()
{
int n;
while (scanf("%d",&n)!=EOF)
{
mp.clear();
for (int i=0;i<n;i++)
{
scanf("%I64d",&val[i]);
}
for (int i=0;i<n;i++)
{
scanf("%I64d",&cost[i]);
}
mp[0]=0;
map <LL,LL>::iterator it;
for (int i=0;i<n;i++)
{
for (it=mp.begin();it!=mp.end();it++)
{
int x=it->first;
int y=it->second;
LL tem=gcd(x,val[i]);//cout<<mp.count(tem)<<":";
if (mp.count(tem)) mp[tem]=min(mp[tem],y+cost[i]);
else mp[tem]=y+cost[i];
}//cout<<endl;
}
if (mp.count(1)) printf("%I64d\n",mp[1]);
else printf("-1\n");
}
}