题意:有n张卡片,每张卡片的价格为c[i],对于第i张卡片,可以从格子x跳到x+l[i]或者x-l[i],问走完所有格子的最小费用为多少
对于卡片a、b,假设a卡片走x步, b卡片走y步,则一共走了 ax+by = c 步,当且仅当c是gcd(a, b)的整数倍时有解,所以最小步数为gcd(a,b)
所以选出的卡片的gcd应当等于1
用map搞下就可以了
#include<iostream> #include<cstring> #include<string> #include<cstdio> #include<stdio.h> #include<algorithm> #include<cmath> #include<set> #include<map> #include<queue> #include<vector> using namespace std; #define inf 0x3f3f3f3f #define eps 1e-9 #define mod 1000000007 #define FOR(i,s,t) for(int i = s; i < t; ++i ) #define REP(i,s,t) for( int i = s; i <= t; ++i ) #define LL long long #define ULL unsigned long long #define pii pair<int,int> #define MP make_pair #define lson id << 1 , l , m #define rson id << 1 | 1 , m + 1 , r #define maxn ( 500 + 10 ) #define maxe ( 500+10 ) map< int, int > gao; map< int , int >:: iterator it; int l[maxn]; int c[maxn]; int gcd( int a, int b ) { return b == 0 ? a : gcd( b, a%b ); } int main () { int n; while( ~scanf("%d", &n ) ) { for( int i = 0; i < n; ++i ) scanf("%d", &l[i] ); for( int i = 0; i < n; ++i ) scanf("%d", &c[i] ); gao[0] = 0; for( int i = 0; i < n; ++i ) { for( it = gao.begin(); it != gao.end(); ++it ) { int t1 = it->first, t2 = it->second; int tmp = gcd( t1, l[i] ); if( gao.count( tmp ) ) gao[tmp] = min( gao[tmp], t2 + c[i] ); else gao[tmp] = t2 + c[i]; } } if( !gao.count( 1 ) ) printf( "-1\n" ); else printf( "%d\n", gao[1] ); gao.clear(); } }