AtCoder Regular Contest #027

oxo-で117th
Bが通らない理由がまだわからない

A

ふつうに60進数で引き算する

int main(){
    int h,m;cin>>h>>m;
    int ans=0;
    ans+=(18-h-1)*60 + 60-m;
    cout << ans << endl;
}

B

UnionFind木で同じ数字を表す文字をUnionしていき、答えの初期値1をそれぞれの集合に数字が含まれるなら1倍、数字が含まれず {s_1, \  s_2} の先頭の文字を含むなら9倍、そうでないなら10倍にしていく。

なぜか通らないので後で見直します。

// UnionFindはSpaghettiSourceのもの

string s,t;
int n;
ull solve(){
    if(n==1){
        if(isdigit(s[0]) || isdigit(t[0])) return 1;
        else return 10;
    }
 
    UnionFind uf(256);
    rep(i,n){
        uf.unionSet(s[i],t[i]);
    }
    map<char,set<char>> m;

    rep(i,n){
        m[uf.root(s[i])].insert(s[i]);
        m[uf.root(t[i])].insert(t[i]);
    }
 
    ull ans=1;
    each(e,m){
        int k=10;
        each(c,e.second)if(isdigit(c))k=1;
        ans*=k;
    }
    if(!isdigit(s[0]) && !isdigit(t[0])){
        ans/=10;
        ans*=9;
    }
    return ans;
}
 
int main(){
    while(cin>>n){
        cin>>s>>t;
        cout<<solve()<<endl;
    }
}

C

ナップサック問題をひねった問題。

{dp(i,x,y):=} {i} 番目までの品物でSチケットを {x} 枚、普通のチケットを {y} 枚残すように取ったときの嬉しさの最大値
とし、残っているチケットの使い方を考えながら更新していく。 使うときの価値はどちらのチケットも同じなので、なくなると困るSチケットを節約して使う。いまいち自信はなかったけどAcceptされた。

int dp[512][512][512]だとMLEするからint dp[2][512][512]としてdp[0]dp[1]を交互に使いまわすように書きなおした。int dp[300][300][300]だと収まったらしい。

int X,Y,N;
int t[512],h[512];
int dp[2][512][512];
 
int solve(){
    memset(dp,0,sizeof(dp));
    rep(i,N){
        rep(x,X+1)rep(y,Y+1){
            dp[(i+1)&1][x][y] = dp[i&1][x][y];
            int uy = min(y,t[i]-1);
            int ux = t[i]-uy;
            if(1<=ux && ux<=x && 0<=uy && uy<=y){
                dp[(i+1)&1][x][y] =
                    max(dp[i&1][x][y],
                        dp[i&1][x-ux][y-uy]+h[i]);
            }
        }
    }
    int ans=0;
    rep(i,X+1)rep(j,Y+1){
        ans=max(ans, dp[N&1][i][j]);
    }
    return ans;
}
 
int main(){
    while(cin>>X>>Y){
        cin>>N;
        rep(i,N)cin>>t[i]>>h[i];
        cout<<solve()<<endl;
    }
}