gcdDP Fox And Jumping : CodeForces

来源:互联网 发布:mac os怎么玩dota2 编辑:程序博客网 时间:2024/06/06 09:11

题目:CodeForces - 510D

time limit per test2 seconds
memory limit per test256 megabytes

Fox Ciel is playing a game. In this game there is an infinite long tape with cells indexed by integers (positive, negative and zero). At the beginning she is standing at the cell 0.

There are also n cards, each card has 2 attributes: length li and cost ci. If she pays ci dollars then she can apply i-th card. After applying i-th card she becomes able to make jumps of length li, i. e. from cell x to cell (x - li) or cell (x + li).

She wants to be able to jump to any cell on the tape (possibly, visiting some intermediate cells). For achieving this goal, she wants to buy some cards, paying as little money as possible.

If this is possible, calculate the minimal cost.

Input
The first line contains an integer n (1 ≤ n ≤ 300), number of cards.

The second line contains n numbers li (1 ≤ li ≤ 109), the jump lengths of cards.

The third line contains n numbers ci (1 ≤ ci ≤ 105), the costs of cards.

Output
If it is impossible to buy some cards and become able to jump to any cell, output -1. Otherwise output the minimal cost of buying such set of cards.

题意:

有个无限长的磁带,一开始处于位置0.有若干张卡片,每张卡片有长度和代价.购买一张卡片后可以无限使用,前进或后退长度的步数,问如何用最小的代价购买若干张卡片,使得可以到达磁带的任意位置.

思路:

动归,f[i][j]表示前I个数字组合出J的最小带价.
根据一个理论,两数a和b正负相加能组合出的最小数字为gcd(a,b),并且能得到所有k*gcd(a,b) k为整数.
所以f[i][gcd(L[i],j)] = min(f[i-1][gcd(L[i],j)],F[i-1][j])

代码:

这个代码中的迭代器是不会失效的,我们可以发现map迭代器在增加元素的时候并不会失效.并且同方向遍历的话,还能遍历到新添加的元素.利用这个特点写的gcd dp代码特别短.

#include <bits/stdc++.h>#define rep(i,a,b) for(int i=(a);i<=(b);++i)#define per(i,a,b) for(int i=(a);i>=(b);--i)using namespace std;const int MAX_N = 300+3;int N,L[MAX_N],C[MAX_N];map<int,int> mp;typedef map<int,int>::iterator Mpit;int gcd(int x,int y){    return y?gcd(y,x%y):x;}int main() {    scanf("%d",&N);    rep(i,1,N) scanf("%d",&L[i]);    rep(i,1,N) scanf("%d",&C[i]);    mp[0]=0;    rep(i,1,N){        for(Mpit iti=mp.begin(); iti!=mp.end(); ++iti){            int gc = gcd(iti->first,L[i]);            mp.count(gc)?mp[gc]=min(mp[gc],iti->second + C[i]):mp[gc]=iti->second + C[i];        }    }    printf("%d",mp[1]?mp[1]:-1);    return 0;}