日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【常规的01背包 POJ3624 UVA562 HDU2546 HDU3466 poj1745】

發布時間:2025/4/16 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【常规的01背包 POJ3624 UVA562 HDU2546 HDU3466 poj1745】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

POJ3624
有N個物品,分別有不同的重量Wi和價值Di,Bessie只能帶走重量不超過M的物品,要是總價值最大,并輸出總價值

//#include <bits/stdc++.h> #include <iostream> #define X 10005 #define inf 0x3f3f3f3f #define PI 3.141592653589793238462643383 #define IO ios::sync_with_stdio(false),cin.tie(0), cout.tie(0); #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; typedef long long ll; const int maxn=1e6+10; using namespace std; int dp[maxn]; int c[maxn]; int w[maxn]; int main() {int n,m;while(cin>>n>>m){for(int i=0; i<n; ++i){cin>>c[i]>>w[i];}for(int i=0; i<n; ++i)for(int j=m; j>=c[i]; --j)dp[j]=max(dp[j],dp[j-c[i]]+w[i]);cout<<dp[m]<<endl;}return 0; }

UVA562
給定n個硬幣,要求將這些硬幣平分以使兩個人獲得的錢盡量多,求兩個人分到的錢最小差值。
?

#include <bits/stdc++.h> #include <iostream> #define X 10005 #define inf 0x3f3f3f3f #define PI 3.141592653589793238462643383 #define IO ios::sync_with_stdio(false),cin.tie(0), cout.tie(0); #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; typedef long long ll; const ll moad=1e9+7; const int maxn=1e6+10; int dp[maxn]; int w[maxn]; int vis[maxn]; int main() {int t,n;cin>>t;while(t--){cin>>n;int sum=0;for(int i=0;i<n;++i)cin>>w[i],sum+=w[i];memset(dp,0,sizeof(dp));for(int i=0;i<n;++i){for(int j=sum/2;j>=w[i];--j){dp[j]=max(dp[j],dp[j-w[i]]+w[i]);}}int __=dp[sum/2],_;_=sum-__;cout<<abs(__-_)<<endl;}return 0; }

HDU2546
這題看上去就知道是01問題了,可是開始怎么轉化都沒有轉化為正確的01背包姿勢
因為沒有明顯的給出來一個背包的容量(做完之后,看出來其實是給出來的,就是這個m-5),然后我wa的姿勢是找所有物品的價值總和去作為容量
撒了一眼題解看是m-5,才知道可以用這個-5剩下的錢去01背包買更多的東西,最后加上那個5塊錢去買加個最大的物品
這個5塊好像用到了貪心的思想 mmp
總結:轉化為正確的01問題姿勢是關鍵
?

#include <bits/stdc++.h> #include <iostream> #define X 10005 #define inf 0x3f3f3f3f #define PI 3.141592653589793238462643383 #define IO ios::sync_with_stdio(false),cin.tie(0), cout.tie(0); #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; typedef long long ll; const ll mod=1e9+7; const int maxn=1e6+10; int dp[maxn]; int w[1005]; int main() {int n,m;while(cin>>n,n){memset(dp,0,sizeof(dp));for(int i=0;i<n;++i) cin>>w[i];cin>>m;if(m<5){cout<<m<<endl;continue;}sort(w,w+n);int _now=m-5;for(int i=0;i<n-1;++i){for(int j=_now;j>=w[i];--j)dp[j]=max(dp[j],dp[j-w[i]]+w[i]);}cout<<m-(w[n-1]+dp[_now])<<endl;}return 0; } #include <bits/stdc++.h> #include <iostream> #define X 10005 #define inf 0x3f3f3f3f #define PI 3.141592653589793238462643383 #define IO ios::sync_with_stdio(false),cin.tie(0), cout.tie(0); #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; typedef long long ll; const ll mod=1e9+7; const int maxn=1e6+10; int dp[maxn]; int w[1005]; int main() {int n,m;while(cin>>n,n){int ans=0;memset(dp,0,sizeof(dp));for(int i=0;i<n;++i) cin>>w[i],ans+=w[i];cin>>m;if(m<5){cout<<m<<endl;continue;}for(int i=0;i<n;++i){for(int j=ans;j>=w[i];--j)dp[j]=max(dp[j],dp[j-w[i]]+w[i]);}cout<<m-dp[ans]<<endl;}return 0; }

HDU3466
先前得01背包問題都是占用多大空間,有多大空間就可以直接進行放入,而這個有個限制體條件
當容量低于特定值得時候就不可以放入,那這樣進行放入得原則就是 需要的容量/本身占有得容量大小 ?這個值越小越好,所謂得性價比越高越好嘛
還有要注意的一點就是當 背包容量小于給的特定值得時候就不可以進行更新dp數組了

#include <bits/stdc++.h> #include <iostream> #define X 10005 #define inf 0x3f3f3f3f #define PI 3.141592653589793238462643383 #define IO ios::sync_with_stdio(false),cin.tie(0), cout.tie(0); #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; typedef long long ll; const ll moad=1e9+7; const int maxn=1e6+10; int q[maxn]; int c[maxn]; int w[maxn]; int dp[maxn]; struct node {double c,q,w; }point[maxn]; bool cmp(node a,node b) {//return a.q-a.c<b.q-b.c;//return a.c*b.q<b.c*a.q;return a.q/a.c<=b.q/b.c; } int main() {int n,m;while(cin>>n>>m){memset(dp,0,sizeof(dp));for(int i=0;i<n;++i)cin>>point[i].c>>point[i].q>>point[i].w;sort(point,point+n,cmp); // for(int i=0;i<n;++i) // cout<<point[i].c<<' '<<point[i].q<<' '<<point[i].w<<endl;for(int i=0;i<n;++i){for(int j=m;j>=point[i].q;--j){dp[j]=max(dp[j],dp[j-int(point[i].c)]+int(point[i].w));}}cout<<dp[m]<<endl;}return 0; }

poj1745

給你n個數,經過加減的操作,看能不能整除K。
dp[i][j]代表前i個數字整除 m 的余數為 j
?

#include <iostream> #include <stdio.h> #include <algorithm> #include <cstring> #define X 10005 using namespace std; int main() {int N,K;cin>>N>>K;int a[X];for(int i=1;i<=N;++i){scanf("%d",&a[i]);a[i]%=K;}int dp[X][K];memset(dp,0,sizeof(dp));//if(a[1]<0)// a[1]+=K;a[1]=(a[1]+K)%K;dp[1][a[1]]=1;for(int i=2;i<=N;++i){for(int j=0;j<K;++j){if(dp[i-1][j]){/* if(j+a[i]>=0)dp[i][j+a[i]]=1;elsedp[i][j+a[i]+K]=1;if(j>=a[i])dp[i][j-a[i]]=1;elsedp[i][j-a[i]+K]=1;*/dp[i][(j+a[i]+K)%K]=1;//保證下標大于0dp[i][(j-a[i]+K)%K]=1;}}}if(dp[N][0])cout<<"Divisible"<<endl;elsecout<<"Not divisible"<<endl;return 0; }

?

#include <iostream> #include <stdio.h> #include <algorithm> #include <cstring> #define X 10005 using namespace std; long long POW(int a,int b) {long long ans=1;while(b){if(b&1){ans*=a;}a*=a;b>>=1;}return ans; } int main() {int N,K;cin>>N>>K;int a[X];for(int i=0;i<N;++i){scanf("%d",&a[i]);}long long n=POW(2,N-1);for(int i=0;i<n;++i){int sum=a[0];//cout<<a[0];for(int j=0;j<N-1;++j){if((i>>j)&1){//cout<<'-'<<a[j+1];sum+=a[j+1];}elsesum-=a[j+1];//,cout<<'+'<<a[j+1];}//cout<<'='<<sum<<"*****"<<sum%K<<endl;if(!(sum%K))//!的優先級比%的高{cout<<"Divisible"<<endl;return 0;}//cout<<endl;}cout<<"Not divisible"<<endl;return 0; } //這個方法是對的,可是在這兒N是10000算出來的n是2^10000會炸的

?

總結

以上是生活随笔為你收集整理的【常规的01背包 POJ3624 UVA562 HDU2546 HDU3466 poj1745】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。