You are on page 1of 8

*bai toan cai tui knapsack dp

struct item{

ll v,w;

};

item dp[maxn];

int main(){

ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

int n,b;

cin>>n>>b;

item a[n];

ll s=0;

for(int i=0;i<n;++i){

cin>>a[i].w>>a[i].v;

s+=a[i].v;

memset(dp,INT_MAX,sizeof(dp));

dp[0].v=1;

//dp

for(int i=0;i<n;++i){ //chay tung phan tu trong mang a[i].w

for(ll j=s;j>=a[i].v;--j){

if(dp[j-a[i].v].v==1){

dp[j].v=1;

dp[j].w=min(a[i].w+dp[j-a[i].v].w,dp[j].w);

}//truy vet-Tìm nghi?m bài toán


for(ll i=s;i>=0;--i){

if(dp[i].v==1&&dp[i].w<=b&&dp[i].w>0){

cout<<i;break;

*LCS longest common subsequence

#include <bits/stdc++.h>

#define el cout<<'\n'

#define maxn 1000006

#define ll long long int

using namespace std;

int main(){

ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

string s1,s2;

cin>>s1>>s2;

int n=s1.size(),m=s2.size();

int dp[n][m];

for(int i=0;i<n;++i){

for(int j=0;j<n;++j){
if(i==0||j==0) dp[i][j]=0;

else if(s1[i]==s2[j]) dp[i][j]=dp[i-1][j-1]+1;

else

dp[i][j]=max(dp[i-1][j],dp[i][j-1]);

int len=dp[n][m],i=0,j=0;//o tung doan i va j thi se luu luon vao dp[i][j] nen
max da duoc cap nhat hoac vua moi duoc cap nhat

string ans="";

while(len){

if(s1[i]=s2[j]){

ans+=s1[i];

i++;j++;

len--;

}else

if(dp[i][j+1] > dp[i+1][j])

j++;

else

i++;

cout<<ans<<endl;

+cần xem lại tóm tắt ý tưởng như sau:


-Tạo 1 bảng 2 chiều dp[i][j] để lưu từng đoạn con thỏa mãn đề bài từ vị trí thứ i->0 của
sâu s1 và từ j->0 của sâu s2

Chạy 2 vòng for duyệt hết các đoạn từ n->0 và từ m->0

Nếu i==0 hoặc j==0 thì khởi tạo dp[0][j]=dp[i][0]=0 trường hợp cơ sở ở rìa đầu bên
trái của bảng

Nếu s1[i]=s2[j] thì dp[i][j]=dp[i-1][j-1] +1 tức là s1[0->i-1] và s2[0->j-1] sẽ lại có


thêm 1 phần tử trùng vì vậy dpij sẽ bằng thằng trước đó của mỗi thằng +1 ,đừng ngu
như tôi khi phân cề quả ảo ở phần i j nó kiểu cố định nên khó tưởng tượng

Nếu ngược lại thì dp[i][j]=max(dp[i][j-1],dp[i-1][j]) stuck vcl☹

Sau vài tháng k học thì mình trở lại(thi hk dí sấp mặt)

Bài toán này có ý tưởng là quay lui(nếu bạn xem code trên magnj thì thấy có code đệ
quy có nhớ)

Ý tưởng là :chỉ số các phần tử trong 2 xâu nếu lưu trong dp thì sẽ +1 cho nó tự nhiên,
từng cái chỉ số trong dp là len đoạn con chung, lưu lại hết nhé

For 2 vòng như trên

Các bạn sẽ k phải cần memset các phtu đều = 0 mà chỉ cần tạo biên = 0

Nếu 2 phần tử si=ti thì mảng sẽ lưu laij kết quả bằng cách lấy độ dài đoạn con chung
trước đó +1:dp[i-1][j-1]+1;

Ab(+1)c

A(+1)cd

Nếu mà chúng khác nhau thì sẽ vẫn cập nhật độ dài đến đó thôi(tư tưởng hay vl) bằng
cách dp[i][j]=max(dp[i-1][j],dp[i][j-1]) các bạn vẽ cây ra thì sẽ hiểu, hiểu đơn giản thì
nó còn 2 cái nhánh thì cập nhật 1 trong 2 nhánh đó

*Không hiểu nữa mn học thuộc cũng được chắc 1 tg sau


sẽ hiểu kiểu ktra ngto lúc mới học đấy k bt sao chạy đến
sqrt(n) rồi 1 tg sau sẽ hiểu thôi đừng mất tg giống mình
quá nhé mn

https://oj.vnoi.info/problem/atcoder_dp_g
#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
vector<int> a[maxn];
int dp[maxn]={0};
int dfs(int u){
if(dp[u]) return dp[u];
for(auto x:a[u]){
dp[u]=max(dfs(x)+1,dp[u]);
}
return dp[u];
}
int main(){
int n,m;
cin>>n>>m;
for(int i=0;i<m;++i){
int x,y;
cin>>x>>y;
x--;y--;
a[x].push_back(y);
}
for(int i=0;i<n;++i){
dfs(i);
}
int ans=0;
for(int i=0;i<n;++i){
ans=max(ans,dp[i]);
}cout<<ans;
}
*code chẳng khác gì trên vnoj

Ý tưởng:

Gọi dp[u] là độ dài đoạn đường dài nhất có thể xuất phát từ đỉnh u

Dữ liệu vào lấy -- for duyệt cho dễ

For qua các đỉnh có thể đến đc

Duyệt dfs(u)

Neo: nếu dp[u]!=0 thì mới return u kiểu đã lấy đc độ dài r thì return là xong(trước đó
đã xử lý thì mới có len)

For các đỉnh x kề với u

Áp dụng ct:dp[u]=max(dp[u],dfs(x)+1) cái đoạn dfs(x)+1 có nghĩa là duyệt dfs bth


nhưng backtr thì +1 vào cái đoạn lớn nhất sau đó

Hết rồi thì return dp[u]

https://oj.vnoi.info/problem/atcoder_dp_k
Ý tưởng :

Tương tự bài toán cái túi

*Một vài chia sẻ của mình với bài toán này là ban đầu mình khá rush và đã
search sol nhưng mà thấy dòng recomend của gg thì nó hiện thêm từ knapsack ở
đằng sau nên đột nhiên mình nghĩ ra ý tưởng của bài knapsack khá hay nhưng
mà mình lại ngu ngu không biết code nên không biết phương án có khả thi hay
không

=>Bài học rút ra là mọi người nên thường xuyên code


và làm phần mình mới học 1 cách liền mạch, vì đa số
các bài toán cơ bản đầu tiên của mỗi chương là cơ sở
hình thành nên các bài toán sau đó và nó chỉ đơn giản
như vậy thôi

You might also like