予鈴

競プロとか備忘録とか…

D - Mixing Experiment

D: Mixing Experiment - AtCoder Beginner Contest 054 | AtCoder

薬品をM_a : M_bにする最小費用を求める問題。
制約も小さいので、 dp[n][ca][cb]でナップサックをすると解ける。
更新をca,cbを薬品の最小のだと思い込んでて時間を溶かした。
具体的には、漸化式を

 int div=(int)gcd((ll)(j+val[i+1].first),(ll)(k+val[i+1].second));
                pii ni=mp((j+val[i+1].first)/div,(k+val[i+1].second)/div);
                cmin(dp[i+1][ni.first][ni.second],dp[i][j][k]+c[i+1]);

こんな形で更新してた。
頭を冷やしてみると、比の足し算はやばい事がわかるし、比はcacbの間にしか成り立たない関係ということもわかる。
反省。

#include<bits/stdc++.h>
#define vi vector<int>
#define vvi vector<vector<int> >
#define vl vector<ll>
#define vvl vector<vector<ll>>
#define vb vector<bool>
#define vc vector<char>
#define vs vector<string>
using ll = long long;
using ld =long double;
#define int ll
#define INF 1e9
#define EPS 0.0000000001
#define rep(i,n) for(int i=0;i<n;i++)
#define loop(i,s,n) for(int i=s;i<n;i++)
#define all(in) in.begin(), in.end()
template<class T, class S> void cmin(T &a, const S &b) { if (a > b)a = b; }
template<class T, class S> void cmax(T &a, const S &b) { if (a < b)a = b; }
#define MAX 9999999
using namespace std;
typedef pair<int, int> pii;
typedef pair<int,pii> piii;
#define mp make_pair
long long gcd(long long a, long long b) {return b ? gcd(b, a % b) : a;}
long long lcm(long long m, long long n ){
    if((0 == m )||( 0 == n ))return 0;
    return ((m / gcd(m, n)) * n);
}
int dp[41][401][401];
signed main(){
    int n; cin>>n;
    pii comp; cin>>comp.first>>comp.second;
    rep(i,n)rep(j,401)rep(k,401)dp[i][j][k]=INF;
    dp[0][0][0]=0;
    vector<pii>val;
    vector<int>c(n);
    rep(i,n){
        pii temp; cin>>temp.first>>temp.second;
        cin>>c[i];
        val.push_back(mp(temp.first,temp.second));
        dp[i][val[i].first][val[i].second]=c[i];
    }
    rep(i,n-1){
        rep(j,401){
            rep(k,401){
                if(dp[i][j][k]==INF)continue;
                cmin(dp[i+1][j][k],dp[i][j][k]);
                pii ni=mp((j+val[i+1].first),(k+val[i+1].second));
                cmin(dp[i+1][ni.first][ni.second],dp[i][j][k]+c[i+1]);
            }
        }
    }
    int ans=INF;
    rep(i,401)rep(j,401){
        int div=gcd(i,j);
        if(i&&j){
        if(i/div==comp.first&&j/div==comp.second)cmin(ans,dp[n-1][i][j]);
        }
    }
    if(ans==INF)ans=-1;
    cout<<ans<<endl;
}