Problem:
0-1 Knapsack Problem
You have
N
items that you want to put them into a knapsack. Item
i
has value
v
i
and weight
w
i
.
You want to find a subset of items to put such that:
The total value of the items is as large as possible.
The items have combined weight at most
W
, that is capacity of the knapsack.
Find the maximum total value of items in the knapsack.
Input
N
W
v
1
w
1
v
2
w
2
:
v
N
w
N
The first line consists of the integers
N
and
W
. In the following lines, the value and weight of the
i
-th item are given.
Output
Print the maximum total values of the items in a line.
Constraints
1 ≤
N
≤ 100
1 ≤
v
i
≤ 1000
1 ≤
w
i
≤ 1000
1 ≤
W
≤ 10000
Sample Input 1
4 5
4 2
5 2
2 1
8 3
Sample Output 1
13
Sample Input 2
2 20
5 9
4 10
Sample Output 2
9

Submitted solutions:

code_snippet: /*
Allaih is Almighty
Bismillahhi Rahmanir Rahim
Baishakh
*/
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds;
#define ll long long
const int mod = 1e9+7;
// s.order_of_key(x) -> values total are small than x
// *s.find_by_order(x)  -> kth small elemnt (index) in pbds
ll dp[102][10002];
ll knap(vector<ll>cost,vector<ll>weight,ll w,ll ind,int n)
{
    if(w == 0 || ind == n) return 0;
    if(dp[ind][w] != -1) return dp[ind][w];
    if(weight[ind] <= w)
    {
       return dp[ind][w] = max(cost[ind] + knap(cost,weight,w - weight[ind],ind + 1,n),
        knap(cost,weight,w,ind + 1,n));
    }
    dp[ind][w] = knap(cost,weight,w,ind+1,n);
    return dp[ind][w];
}
int main()
{
    memset(dp,-1,sizeof(dp));
    ll n,w;
    cin>>n>>w;
    vector<ll>cost(n),weight(n);
    for(int i = 0;i<n;i++)
    {
        cin>>cost[i]>>weight[i];
    }
    cout<<knap(cost,weight,w,0,n)<<endl;
  return 0;
}


//Tata Goodbye Khatam
accuracy: 1
time_ms: 130
memory_kb: 11600
final_rank: 1

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll = long long;
using Graph = vector<vector<int>>;
const int dx[8] = {1, 0, -1, 0, 1, 1, -1, -1};
const int dy[8] = {0, 1, 0, -1, 1, -1, 1, -1};

#define rep(i, a, b) for(int i = a; i < b; i++)
#define all(v) v.begin(), v.end()
#define YESNO(flag) cout << (flag ? "Yes" : "No") << "\n"
#define inf 1070000000
#define INF 4500000000000000000
#define MOD 998244353
//#define MOD 1000000007
#define pi 3.14159265358979

template<class T> inline bool chmin(T& a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template<class T> inline bool chmax(T& a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

//xのn乗
ll llpow(ll x, ll n) {
    ll ans = 1;
    while(n > 0) {
        if(n & 1) ans *= x;
        x *= x;
        n >>= 1; 
    }
    return ans;
}
ll modpow(ll x, ll n, ll mod) {
    ll ans = 1;
    while(n > 0) {
        if(n & 1) ans = ans * x % mod;
        x = x * x % mod;
        n >>= 1;
    }
    return ans;
}
//nの階乗
ll fact(ll n) {
    if(n == 0) return 1;
    else return n * fact(n-1);
}
//素数判定
bool is_prime(long long x) {
    if(x == 1) return false;
    
    for(long long i = 2; i*i <= x; i++) {
        if(x % i == 0) return false;
    }
    return true;
}

//座標圧縮
vector<int> compress(vector<int> A) {
    vector<int> B = A;

    sort(B.begin(), B.end());
    B.erase(unique(B.begin(), B.end()), B.end());

    vector<int> res(A.size());
    for(int i = 0; i < (int)A.size(); i++) {
        res[i] = lower_bound(B.begin(), B.end(), A[i]) - B.begin();
    }
    return res;
}

//正方形グリッドの右回転
void rotate_right(vector<vector<char>> &S) {
    int N = S.size();
    auto T = S;
    rep(i,0,N) rep(j,0,N) {
        T[i][j] = S[N-1-j][i];
    }
    S = T;
}
//左回転
void rotate_left(vector<vector<char>> &S) {
    int N = S.size();
    auto T = S;
    rep(i,0,N) rep(j,0,N) {
        T[i][j] = S[j][N-1-i];
    }
    S = T;
}

//2点(a,b)と(x,y)の距離
double dist(ll a, ll b, ll x, ll y) {
    return sqrt((a-x)*(a-x) + (b-y)*(b-y));
}
int man(int a, int b, int x, int y) {
    return abs(a-x) + abs(b-y);
}

//桁数
int digit(ll N) {
    if(N <= 9) return 1;

    return 1 + digit(N / 10);
}
//A進数文字列NをB進数に変換. A,Bは10以下
string base_change(string N, ll A, ll B) {
    ll X = stoll(N), Y = 0;

    ll i = 1;
    while(X != 0) {
        Y += (X % 10) * i;
        i *= A;
        X /= 10;
    }

    X = Y, Y = 0;
    i = 1;
    while(X != 0) {
        Y += (X % B) * i;
        i *= 10;
        X /= B;
    }

    return to_string(Y);
}
//回文判定
bool palin(string S) {
    rep(i,0,S.size()) {
        if(S[i] != S[S.size()-1-i]) return false;
    }
    return true;
}


//DFS
void dfs(const Graph &G, int v, vector<bool> &seen) { 
    seen[v] = true;
    
    for (auto next_v : G[v]) { 
        if (!seen[next_v]) {
            dfs(G, next_v, seen);
        }
    }
}
void griddfs(const vector<vector<char>> &G, int x, int y, vector<vector<bool>> &seen) {
    int H = G.size(), W = G[0].size();
    seen[x][y] = true;
    
    for (int i = 0; i < 8; i++) { 
        int nx = x + dx[i], ny = y + dy[i];
        if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
        if (!seen[nx][ny] and G[nx][ny] != '#') griddfs(G, nx, ny, seen);
    }
}
//BFS
void bfs(const Graph &G, int v, vector<int> &dist) {
    rep(i,0,dist.size()) dist[i] = inf;
    dist[v] = 0;
    queue<int> q;
    q.push(v);
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        for(auto next_u : G[u]) {
            if(dist[next_u] == inf) {
                dist[next_u] = dist[u] + 1;
                q.push(next_u);
            }
        }
    }
}
void gridbfs(const vector<vector<char>> &G, int x, int y, vector<vector<int>> &dist) {
    int H = G.size(), W = G[0].size();
    rep(i,0,H) rep(j,0,W) dist[i][j] = inf;
    dist[x][y] = 0;
    queue<pair<int, int>> q;
    q.push(make_pair(x, y));
    while(!q.empty()) {
        int x = q.front().first, y = q.front().second;
        q.pop();
        for(int i = 0; i < 4; i++) {
            int nx = x + dx[i], ny = y + dy[i];
            if(nx < 0 or nx >= H or ny < 0 or ny >= W) continue;
            if(dist[nx][ny] == inf and G[nx][ny] != '#') {
                dist[nx][ny] = dist[x][y] + 1;
                q.push(make_pair(nx, ny));
            }
        }
    }
}
//ワーシャル・フロイド
void floyd(vector<vector<ll>> &G) {
    int N = G.size();
    for (int k = 0; k < N; k++){
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if(G[i][j] > G[i][k] + G[k][j]) {
                    G[i][j] = G[i][k] + G[k][j];
                }
            }
        }
    }
}

void solve() {
}

int main() {
    int N, W; cin >> N >> W;
    vector<vector<int>> dp(N+1, vector<int>(100200, 0));
    rep(i,0,N) {
        int v, w; cin >> v >> w;
        rep(j,0,W+1) {
            chmax(dp[i+1][j], dp[i][j]);
            chmax(dp[i+1][j+w], dp[i][j] + v);
        }
    }
    for(int i = W; i >= 0; i--) {
        if(dp[N][i] != 0) {
            cout << dp[N][i] << "\n";
            return 0;
        }
    }
    cout << 0 << "\n";
    
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 42988
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
//#include <atcoder/all>
//using namespace atcoder;
//#include <unordered_set>
//#include <boost/multiprecision/cpp_int.hpp>
//using namespace boost::multiprecision;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
using P = pair<ll,ll>;

#define rep(i,n) for (ll i = 0; i < ll(n); ++i)
#define REP(i,x,n) for (ll i = x; i < ll(n); ++i)
#define DREP(i, r, l) for (ll i = (ll)(r)-1; i >= (ll)(l); --i)
#define drep(i,n) DREP(i, n, 0)
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define MAX *max_element
#define MIN *min_element
#define pb push_back
#define pf push_front
#define ppb pop_back
#define eb emplace_back
#define fi first
#define se second
#define p_queue priority_queue

using namespace std; // std::を省略するために追加

/* ========== UNIVERSAL DEBUG ========== */
#ifdef LOCAL
#define dbg(...) cerr << "\e[33m[ " << #__VA_ARGS__ << " ] = ", debug_out(__VA_ARGS__), cerr << " (" << __LINE__ << ")\e[0m\n"
#else
#define dbg(...) (void)0
#endif

// 型がイテラブル（反復可能）かどうかを判定するためのヘルパー
template<class T, class = void> struct is_iterable : false_type {};
template<class T>
struct is_iterable<T, std::void_t<decltype(std::begin(std::declval<T>())), decltype(std::end(std::declval<T>()))>> : true_type {};
template<class T> constexpr bool is_iterable_v = is_iterable<T>::value;

// 様々なデータ型を出力するための関数たち

// 基本的な型（int, doubleなど）を出力
// より特定のオーバーロードが適用されない場合の最終的なフォールバック
template<class T>
std::enable_if_t<!is_iterable_v<T> && !std::is_pointer_v<T> && !std::is_same_v<T, std::string>, void>
debug_pr(const T& x){
    cerr << x;
}

// string型を出力（引用符で囲む）
inline void debug_pr(const string& s){ cerr << '"' << s << '"'; }

// char* などのCスタイル文字列を出力
inline void debug_pr(const char* s) { cerr << '"' << s << '"'; }

// pair型を出力 (first, second) の形式
template<class A,class B> void debug_pr(const pair<A,B>& p){ cerr << '('; debug_pr(p.first); cerr << ", "; debug_pr(p.second); cerr << ')'; }

// tuple型を出力するためのヘルパー（再帰的に要素を出力）
template<size_t I=0,class... Ts>
std::enable_if_t<I==sizeof...(Ts)> debug_tuple(const tuple<Ts...>&) {} // タプルの要素をすべて処理したら終了
template<size_t I=0,class... Ts>
std::enable_if_t<I<sizeof...(Ts)> debug_tuple(const tuple<Ts...>& t){
    if(I) cerr << ", "; // 2番目以降の要素の前にカンマを追加
    debug_pr(std::get<I>(t)); // 現在の要素を出力
    debug_tuple<I+1>(t); // 次の要素を処理
}

// tuple型を出力
template<class... Ts> void debug_pr(const tuple<Ts...>& t){
    cerr << '('; debug_tuple(t); cerr << ')'; // (要素1, 要素2, ...) の形式
}

// イテラブルな型（vector, listなど、ただしstringは除く）を出力
// このオーバーロードが選ばれるように、SFINAEで制約を追加
template<class T>
std::enable_if_t<is_iterable_v<T> && !std::is_same_v<T,string>, void>
debug_pr(const T& v){
    cerr << '['; bool f=0; // 最初だけスペースを入れないためのフラグ
    for(const auto& x:v){
        if(f) cerr << ' '; // 2番目以降の要素の前にスペースを追加
        debug_pr(x); // 各要素を出力
        f=1; // フラグを立てる
    }
    cerr << ']'; // [要素1 要素2 ...] の形式
}

// ポインタを出力 (アドレスではなく、指し示す値を出力)
// nullptr_t は std::nullptr の型です
inline void debug_pr(std::nullptr_t) { cerr << "nullptr"; }
template<class T>
std::enable_if_t<std::is_pointer_v<T>, void>
debug_pr(const T& p) {
    if (p == nullptr) {
        cerr << "nullptr";
    } else {
        cerr << '*'; // ポインタが指す値であることを示す
        debug_pr(*p); // ポインタが指す値を出力
    }
}


// 可変長引数を処理するための関数
void debug_out(){ } // 引数がない場合の終端
template<class Head,class... Tail>
void debug_out(const Head& h,const Tail&... tl){
    debug_pr(h); // 最初の引数を出力
    if constexpr(sizeof...(tl)) { cerr << ", "; debug_out(tl...); } // 残りの引数があれば、カンマの後に再帰呼び出し
}


template<typename T, typename U>
ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << "(" << p.first << ", " << p.second << ")";
    return os;
}

template<typename T, typename U> inline void println(const vector<pair<T,U>>& vec) { for(auto& [x,y]:vec) cout<<"("<<x<<","<<y<<") "; cout<<"\n"; }
inline void print(vector<char>& v) { for (char c : v) cout << c; }
inline void println(vector<char>& v) { print(v); cout << '\n'; }
template<class T> inline bool chmax(T &a, T b) { return a < b ? a = b, 1 : 0; }
template<class T> inline bool chmin(T &a, T b) { return a > b ? a = b, 1 : 0; }
void dprint(ld x) { printf("%.30Lf\n",x); }
template<class... T> inline void input(T&... a) { ((cin >> a), ...); }
template <class T> inline void input(vector<T> &v) { for (T &x : v) cin >> x; }
template<class T, class... U> inline void print(const T& a, const U&... b) { cout << a; ((cout << b), ...); }
template<class T, class... U> inline void println(const T& a, const U&... b) { print(a, b...); cout << '\n'; }
inline void println() { cout << '\n'; }
template<class T> inline void print(vector<T>& A) { rep(i, A.size()) { if (i) cout << ' '; cout << A[i]; } }
template<class T> inline void println(vector<T>& A) { print(A); cout << '\n'; }
inline void yn(bool ok) { cout << (ok ? "Yes\n" : "No\n"); }

const ll INF = (1LL << 62) - (1LL << 31) - 1;
const ll mod = 1e9 + 7;

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

// ２次元累積和のライブラリ貼ってる
// 2^nの数え上げはDPで解けるかも?
// 全探索の高速化といえばDP
// DPは配る遷移ともらう遷移の両方を考察する
// 問題の振り返り書け
// めんどくさい計算とかは関数にしたら楽
// 誤差などが怖いときは移項などをして整数で考えるようにする 
// 式変形をしたら見通しが良くなる
// 問題を分解する
// すべての問題を解けると思って考える
// ゲームをしているならDPを考える

// alias xx='g++ -D_GLIBCXX_DEBUG -fsanitize=undefined,address -fno-sanitize-recover=all -Wall -Wextra -Wshadow'

void solve() {
	ll n,w;
	input(n,w);
	vector<ll> v(n),u(n);
	rep(i,n) input(v[i],u[i]);
	map<P,ll> memo;
	auto f = [&](auto self,ll d,ll now) -> ll {
		if(d >= n) return 0;
		if(memo.count(P(d,now))) return memo[P(d,now)];
		ll res = 0;
		if(now+u[d] <= w) {
			res = max(self(self,d+1,now+u[d])+v[d],self(self,d+1,now));
		}else {
			res = max(res,self(self,d+1,now));
		}
		return memo[P(d,now)] = res;
	};

	println(f(f,0,0));
}

int main() {
	ios::sync_with_stdio(false);
  cin.tie(nullptr);
	solve();
  return 0;
}
accuracy: 1
time_ms: 370
memory_kb: 55680
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;

int main() {
 int N,W;
 cin >> N >> W;
 vector<int>v(N);
 vector<int>w(N);
 for(int i = 0; i < N; i++){
cin >> v[i] >> w[i];
 }

 vector<vector<int>>DP(N+10,vector<int>(100100,0));
 for(int i = 0; i < N; i++){

    for(int sum_w = 0; sum_w <= W ; sum_w++){

        if(sum_w >= w[i]){
DP[i+1][sum_w] = max(DP[i+1][sum_w],DP[i][sum_w-w[i]]+v[i]);
        }
        DP[i+1][sum_w] = max(DP[i+1][sum_w],DP[i][sum_w]);
    }
 }
 cout << DP[N][W] << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 46644
final_rank: 3