SRM 594 DIV1 Easy - AstronomicalRecords (復習×○)
問題
http://community.topcoder.com/stat?c=problem_statement&pm=12804&rd=15706
・惑星がn個存在する。
・惑星の相対サイズを測るシステムA,Bが存在する。
・各システムは太陽からの距離が近い順からランダムな数を選び、そのシステムとの相対距離を計算する。
このとき、存在しうる惑星の数の最小値を求める。
解き方
相対距離の最大値は10^9のため全ての値について全探索はできない。
そこで、要素数は最大50であることから50*50=2500分だけの組み合わせに対して調べればよい。
このとき、掛け算で値を考えると小数になるため計算しにくい。
そのため、最小公倍数の計算の仕方を用いて、A[i],B[j]のペアを選んだときBの要素には全てA[i]をかけ、Aの要素には全てB[j]をかければよい。
上記の処理後は、LCM(Longest Common Sequence)問題に帰着できる。
dpはAの要素数とBの要素数の2次元配列を用いる。
dp[i][j]はi,jに到達するまでの最大値と定義し、状態遷移にて答えを求める。
コード
using namespace std;
#define all(c) (c).begin(),(c).end()
#define FORE(i,d,e) for(int i=d;i<e;i++)
#define FOR(i,s,e) for (int i = int(s); i != int(e); i++)
#define FORIT(i,c) for (typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define ISEQ(c) (c).begin(), (c).end()
class AstronomicalRecords {
public:
int gcd(int x,int y){
return y ? gcd(y,x%y) : x;
}
int minimalPlanets(vector<int> A, vector<int> B) {
int n=A.size(),m=B.size();
int ret=0;
FORE(i,0,n)FORE(j,0,m){
int g=gcd(A[i],B[j]);
vector<long long> a,b;
FORE(k,0,n)a.push_back((long long)A[k]*B[j]/g);
FORE(k,0,m)b.push_back((long long)B[k]*A[i]/g);
int dp[n+1][m+1];
memset(dp,0,sizeof(dp));
FORE(k,0,n)FORE(l,0,m){
if(a[k]==b[l])dp[k+1][l+1]=max(dp[k+1][l+1],dp[k][l]+1);
dp[k+1][l]=max(dp[k+1][l],dp[k][l]);
dp[k][l+1]=max(dp[k][l+1],dp[k][l]);
}
FORE(k,0,n+1)FORE(l,0,m+1)ret=max(ret,dp[k][l]);
}
return n+m-ret;
}
};
#define all(c) (c).begin(),(c).end()
#define FORE(i,d,e) for(int i=d;i<e;i++)
#define FOR(i,s,e) for (int i = int(s); i != int(e); i++)
#define FORIT(i,c) for (typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define ISEQ(c) (c).begin(), (c).end()
class AstronomicalRecords {
public:
int gcd(int x,int y){
return y ? gcd(y,x%y) : x;
}
int minimalPlanets(vector<int> A, vector<int> B) {
int n=A.size(),m=B.size();
int ret=0;
FORE(i,0,n)FORE(j,0,m){
int g=gcd(A[i],B[j]);
vector<long long> a,b;
FORE(k,0,n)a.push_back((long long)A[k]*B[j]/g);
FORE(k,0,m)b.push_back((long long)B[k]*A[i]/g);
int dp[n+1][m+1];
memset(dp,0,sizeof(dp));
FORE(k,0,n)FORE(l,0,m){
if(a[k]==b[l])dp[k+1][l+1]=max(dp[k+1][l+1],dp[k][l]+1);
dp[k+1][l]=max(dp[k+1][l],dp[k][l]);
dp[k][l+1]=max(dp[k][l+1],dp[k][l]);
}
FORE(k,0,n+1)FORE(l,0,m+1)ret=max(ret,dp[k][l]);
}
return n+m-ret;
}
};