Combinatorial - 0-1 Knapsack Problem

ナップザック問題 | 動的計画法 | Aizu Online Judge

シンプルなナップザック問題。

int main() {
    int N, W; cin >> N >> W;
    int v[105], w[105];
    for (int i = 0; i < N; i++) cin >> v[i] >> w[i];
    int dp[105][10005];
    memset(dp, -1, sizeof(dp));
    int res = 0;
    dp[0][0] = 0;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j <= W; j++) {
            int k = j - w[i];
            if (k >= 0 && dp[i][k] >= 0) {
                dp[i + 1][j] = max(dp[i][j], dp[i][k] + v[i]);
            } else {
                dp[i + 1][j] = dp[i][j];
            }
            res = max(res, dp[i + 1][j]);
        }
    }

    printf("%d\n", res);
    return 0;
}

コイン問題 | 動的計画法 | Aizu Online Judge

コイン問題 | 動的計画法 | Aizu Online Judge

DPコースなるものを発見したので解いていこうと思う。

貪欲法でいける?と思ったが、コインの額面が半端なのでDPで解いていく。

int main() {
    int n, m; cin >> n >> m;
    int coins[25];
    int dp[25][50005];
    for (int i = 0; i < m; i++) cin >> coins[i];

    for (int i = 0; i < 25; i++) fill(dp[i], dp[i] + 50005, 1000*1000);
    dp[0][0] = 0;
    for (int i = 0; i < m; i++) {
        for (int j = 0; j <= n; j++) {
            dp[i + 1][j] = min(dp[i + 1][j], dp[i][j]);
            int k = j - coins[i];
            if (k >= 0) {
                dp[i + 1][j] = min(dp[i + 1][j], dp[i][k] + 1);
                dp[i + 1][j] = min(dp[i + 1][j], dp[i + 1][k] + 1);
            }
        }
    }
    printf("%d\n", dp[m][n]);
    return 0;
}

0537: Bingo | Aizu Online Judge

Bingo | Aizu Online Judge

状態数をうまく削減しないといけない。

int N, M, S;
int dp[50][3005];

int mod = 100000;

int main() {
    while (1) {
        cin >> N >> M >> S;
        if (N == 0) break;
        memset(dp, 0, sizeof(dp));
        N *= N;
        dp[0][0] = 1;
        for (int i = 1; i <= M; i++) {

            for (int j = N; j>0; j--){
                for(int k=i;k<=S;k++){
                    dp[j][k]=(dp[j][k]+dp[j-1][k-i])%mod;
                }
            }
        }
        printf("%d\n", dp[N][S]);
    }
    return 0;
}

POJ 2441 : Arrange the Bulls

POJ 2441 : Arrange the Bulls

通ったんだけどこれでいいのかな。。

int N, M;
int cows[30][30] = {};
int memo[(1 << 20) + 1] = {};

int solve(int i, int S) {
    if (memo[S] != -1) {
        return memo[S];
    }

    if (i == N) return 1;

    int res = 0;
    for (int j = 0; j < M; j++) {
        if (cows[i][j] && !(S & (1 << j))) {
            res += solve(i+1, S | (1 << j));
        }
    }
    return memo[S] = res;
}

int main() {
    memset(memo, -1, sizeof(memo));
    cin >> N >> M;
    for (int i = 0; i < N; i++) {
        int t;
        cin >> t;
        for (int j = 0; j < t; j++) {
            int t2;
            cin >> t2;
            t2--;
            cows[i][t2] = 1;
        }
    }
    cout << solve(0, 0) << endl;
    return 0;
}

Block | Aizu Online Judge

Block | Aizu Online Judge

特に難しいことはないけど、入力ケースが多いので少しめんどくさい。

int mp[105][105];
bool visited[105][105];
int w, h;
int xs, ys;
int xg, yg;
int n;
int col;

int dx[]={-1,1,0,0};
int dy[]={0,0,1,-1};

void solve(int x, int y) {
    visited[x][y]=1;
    if (x==xg&&y==yg) return;
    for (int i = 0; i < 4; i++) {
        int nx = x + dx[i], ny = y + dy[i];
        if (nx<1 || nx > w || ny < 1 || ny > h) continue;
        if (visited[nx][ny]) continue;
        solve(nx, ny);
    }
}

int main() {
    while (1) {
        memset(mp, 0, sizeof(mp));
        memset(visited, 0, sizeof(visited));
        cin >> w >> h;
        if (w==0&&h==0) break;
        cin >> xs >> ys;
        cin >> xg >> yg;
        cin >> n;
        for (int i = 0; i < n; i++) {
            int c, d, x, y; cin >> c >> d >> x >> y;
            int jl, kl;
            if (d==0)
                jl = 4, kl = 2;
            else
                jl = 2; kl = 4;

            for (int j = 0; j < jl; j++)
                for (int k = 0; k < kl; k++)
                    mp[x+j][y+k]=c;
        }
        col = mp[xs][ys];
        if (col != mp[xg][yg] || !col){
            cout << "NG" << endl;
            continue;
        }
        for (int i = 1; i <= w; i++) {
            for (int j = 1; j <= h; j++){
                if (mp[i][j] != col){
                    visited[i][j]=1;
                }
            }
        }
        solve(xs, ys);
        if (visited[xg][yg]) {
            cout << "OK" << endl;
        } else {
            cout << "NG" << endl;
        }
    }
    return 0;
}

The Number of Island

島の数 | Aizu Online Judge

教科書的なDFSの問題なんだが、入力ケースの終わりがちょっと特殊だった。 Patisserie | Aizu Online Judgeを彷彿とさせる。。

bool visited[13][13];
string mp[13];
 
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
 
void solve(int x, int y) {
    visited[x][y]=1;
    for (int i =0; i < 4;i++) {
        int nx=x+dx[i], ny=y+dy[i];
        if (0<=nx&&nx<12&&0<=ny&&ny<12) {
            if (!visited[nx][ny]){
                solve(nx, ny);
            }
        }
    }
}
 
int main() {
    while (1) {
        string s;
        for (int i=0;i<4;i++){
            getline(cin, s);
            if (s!="")break;
        }
        if (s=="")break;
        mp[0]=s;
        for(int i = 0; i < 11; i++) cin >> mp[i+1];
        memset(visited, 0, sizeof(visited));
 
        for (int i = 0; i < 12; i++) {
            for (int j = 0; j < 12; j++) {
                if (mp[i][j]=='0') {
                    visited[i][j]=1;
                }
            }
        }
        int res=0;
        for(int i=0;i<12;i++) {
            for(int j=0;j<12;j++) {
                if (visited[i][j])continue;
 
                if (mp[i][j]=='1'){
                    solve(i, j);
                    res++;
                }
            }
        }
        cout << res << endl;
    }
    return 0;
}

Sum of Integers

整数の和 | Aizu Online Judge

こちらもに引き続き、シンプルに全通り試してみる。

int n, s;
 
int solve(int now, int left, int sum) {
    if (left == 0) {
        return sum == s;
    }
    if (now > 9) return 0;
    int res = 0;
    res+=solve(now+1, left-1, sum+now);
    res+=solve(now+1, left, sum);
    return res;
}
 
int main() {
    while (1) {
        cin >> n >> s;
        if (n==0&&s==0)break;
        cout << solve(0, n, 0) << endl;
    }
    return 0;
}