标签:
这段时间要开始刷dp了,记录点点滴滴。21:33:51
一.基础dp:
1.hdu.2602.Bone Collector.
这道是基础的01背包。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int MAXN=1000+10; 5 int w[MAXN]; 6 int v[MAXN]; 7 int dp[MAXN]; 8 int main() 9 { 10 int test; 11 scanf("%d",&test); 12 while(test--) 13 { 14 int n,V; 15 scanf("%d%d",&n,&V); 16 for(int i=1;i<=n;i++) 17 scanf("%d",&w[i]); 18 for(int i=1;i<=n;i++) 19 scanf("%d",&v[i]); 20 for(int j=0;j<=V;j++) 21 dp[j]=0; 22 for(int i=1;i<=n;i++) 23 for(int j=V;j>=v[i];j--) 24 { 25 dp[j]=max(dp[j],dp[j-v[i]]+w[i]); 26 } 27 int ans=0; 28 for(int j=0;j<=V;j++) 29 if(dp[j]>ans) 30 ans=dp[j]; 31 printf("%d\n",ans); 32 } 33 return 0; 34 }
2.poj.3624.Charm Bracelet.
基础01背包,注意下标的最大值为物品数还是背包容量最大值。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int MAXN=3410; 5 const int MAXM=13000; 6 int w[MAXN]; 7 int cost[MAXN]; 8 int dp[MAXM]; 9 int main() 10 { 11 int n,m; 12 while(scanf("%d%d",&n,&m)!=EOF) 13 { 14 for(int i=1;i<=n;i++) 15 scanf("%d%d",&cost[i],&w[i]); 16 for(int j=0;j<=m;j++) 17 dp[j]=0; 18 for(int i=1;i<=n;i++) 19 for(int j=m;j>=cost[i];j--) 20 dp[j]=max(dp[j],dp[j-cost[i]]+w[i]); 21 int ans=0; 22 for(int i=0;i<=m;i++) 23 if(dp[i]>ans) 24 ans=dp[i]; 25 printf("%d\n",ans); 26 } 27 return 0; 28 }
3.hdu.2546.饭卡.
先预留5元去买最贵的菜,注意n==0 时结束。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int maxn=1000+5; 5 const int maxm=1000+5; 6 int a[maxn]; 7 int dp[maxm]; 8 int main() 9 { 10 int n; 11 while(scanf("%d",&n)!=EOF) 12 { 13 if(n==0) 14 break; 15 for(int i=1;i<=n;i++) 16 scanf("%d",&a[i]); 17 int m; 18 scanf("%d",&m); 19 if(m<5) 20 printf("%d\n",m); 21 else 22 { 23 int mm=m-5; 24 sort(a+1,a+n+1); 25 for(int i=0;i<=mm;i++) 26 dp[i]=0; 27 for(int i=1;i<n;i++) 28 for(int j=mm;j>=a[i];j--) 29 dp[j]=max(dp[j],dp[j-a[i]]+a[i]); 30 int ans=0; 31 for(int i=0;i<=mm;i++) 32 if(dp[i]>ans) 33 ans=dp[i]; 34 printf("%d\n",m-ans-a[n]); 35 } 36 } 37 return 0; 38 }
4.uva.562.Dividing Coins
平衡问题,先累加硬币的总价值,然后sum/2,作为背包容量对n个硬币进行选择,求出其最大价值。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int MAXN=105; 5 const int MAXM=30000; 6 int dp[MAXM]; 7 int coin[MAXN]; 8 int main() 9 { 10 int test; 11 scanf("%d",&test); 12 while(test--) 13 { 14 int n; 15 scanf("%d",&n); 16 int sum=0; 17 for(int i=1;i<=n;i++) 18 { 19 scanf("%d",&coin[i]); 20 sum+=coin[i]; 21 } 22 int half=sum/2; 23 for(int i=0;i<=half;i++) 24 dp[i]=0; 25 for(int i=1;i<=n;i++) 26 for(int j=half;j>=coin[i];j--) 27 dp[j]=max(dp[j],dp[j-coin[i]]+coin[i]); 28 int cnt=0; 29 for(int i=0;i<=half;i++) 30 if(dp[i]>cnt) 31 cnt=dp[i]; 32 half=sum-cnt; 33 int ans; 34 if(half>cnt) 35 ans=half-cnt; 36 else 37 ans=cnt-half; 38 printf("%d\n",ans); 39 } 40 return 0; 41 }
5.hdu.2955.Robberies.
被抓的概率比较难算,加之精度问题,所以转换为不被抓的概率。
若以概率为代价,不是整数,无法作为下标,所以以银行总价值为背包容量,单个银行的储蓄为体积,以不被抓的概率作为价值。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int MAXN=105; 5 const int MAXM=11000; 6 double dp[MAXM]; 7 int money[MAXN]; 8 double pro[MAXN]; 9 int main() 10 { 11 int test; 12 scanf("%d",&test); 13 while(test--) 14 { 15 int n; 16 double P; 17 scanf("%lf%d",&P,&n); 18 P=1.0-P; 19 int sum=0; 20 for(int i=1;i<=n;i++) 21 { 22 scanf("%d%lf",&money[i],&pro[i]); 23 sum+=money[i]; 24 pro[i]=1.0-pro[i]; 25 } 26 for(int i=0;i<=sum;i++) 27 dp[i]=0; 28 dp[0]=1; 29 for(int i=1;i<=n;i++) 30 for(int j=sum;j>=money[i];j--) 31 dp[j]=max(dp[j],dp[j-money[i]]*pro[i]); 32 int ans=0; 33 for(int i=0;i<=sum;i++) 34 if(dp[i]>=P&&i>ans) 35 ans=i; 36 printf("%d\n",ans); 37 } 38 return 0; 39 }
标签:
原文地址:http://www.cnblogs.com/-maybe/p/4266120.html