赞
踩
1.最大价值且恰好装满:dp[0]=0 其他负无穷
2.最小价值且恰好装满:dp[0]=0 其他正无穷
3.不恰好装满:都为0
- #include<cstdio>
- int main()
- {
- //W 总重量 n 物品个数 v[i]价值 W[i] 重量
- //一维
- int dp[MAX],v[MAX],w[MAX];
- //01背包问题
- for(int i=1;i<=n;i++)
- for(int j=W;j>=w[i];j--)
- dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
- //完全背包问题
- for(int i=1;i<=n;i++)
- for(int j=w[i];j<=W;j++)
- dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
- //多重背包 n[i] 个数
- void zero(int cost,int val)
- {
- for(int i=W;i>=cost;i--)
- dp[i]=max(dp[i],dp[i-cost])+val;
- }
- void comple(int cost,int val)
- {
- for(int i=cost;i<=W;i++)
- dp[i]=max(dp[i],dp[i-cost]+val);
- }
- void muti(int cost,int val,int num)
- {
- if(cost*num>=W)//num个里面可以凑够W
- {
- comple(cost,val);
- }
- else{//否则二进制优化找01背包
- int k=1;
- while(k<num)
- {
- zero(k*cost,k*val);
- num-=k;
- k*=2;
- }
- zero(num*cost,num*val);
- }
- }
- for(int i=1;i<=n;i++)
- muti(w[i],v[i],n[i]);
- //分组背包
- for(int i=1;i<=k;i++)//k为组数
- {
- for(int j=W;j>=0;j--)//此时每组只能选一个
- {
- for(int t=1;t<=n;t++)//每组个数
- {
- dp[i][j]=max(dp[i][j],dp[i][j-w[t]]+v[t]);//n为每组个数
- }
- }
- }
- return 0;
- }

- int dp[(1<<n)][maxn];
- int dis[maxn][maxn];
- const int inf=0x3f3f3f3f;
- void slove()
- {
- //n表示点的个数
- memset(dp,inf,sizeof(dp));
- dp[(1<<n)-1][0]=0;//dp[s][v]表示从v出发,访问未访问的点的最短路径和,其中s表示已经访问点的集合
- for(int s=(1<<n)-2;s>=0;s--)//每种状态进行枚举
- {
- for(int v=0;v<n;v++)
- {
- for(int u=0;u<n;u++)
- {
- if(!(s&(1<<u)))//u不在s中
- {
- dp[s][v]=min(dp[s][v],dp[s|(1<<u)][u]+dis[v][u]);
- }
- }
- }
- }
- printf("%d\n",dp[0][0])//结果为 0出发 所有点均未访问
- }

续~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。