poj 2923(状态压缩dp)
题意:就是给了你一些货物的重量,然后给了两辆车一次的载重,让你求出最少的运输次数。
分析:首先要从一辆车入手,搜出所有的一次能够运的所有状态,然后把两辆车的状态进行合并,最后就是解决了,有两种方法:
1.组合解决:
代码实现:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int n,sum1,sum2,a[15]; int st1[1500],st2[1500],st[1500],num1,num2,num; int total[1500],all; //st1数组保存的是第一辆车能够一次运走的所有状态,同理st2数组为第二辆车的 //st数组保存的是两辆车一次能够运走的所有状态 void dfs(int f,int flag,int x,int s)//开始的时候这个dfs是作死的错,说明dfs写得还不够熟练 { int i,j,temp; if(flag==1&&f==n+1) st1[num1++]=x; else if(f==n+1) st2[num2++]=x; if(f>n) return ; temp=1<<(n-f); if(flag==1) { if(s+a[f]<=sum1) dfs(f+1,flag,x+temp,s+a[f]); dfs(f+1,flag,x,s); } else { if(s+a[f]<=sum2) dfs(f+1,flag,x+temp,s+a[f]); dfs(f+1,flag,x,s); } } void hebing()//两辆车的状态合并 { int i,j,t=2; int visited[1500],temp; memset(visited,0,sizeof(visited)); for(i=1;i<num1;i++) for(j=1;j<num2;j++) { temp=st1[i]|st2[j]; if(visited[temp]==0) { st[num++]=temp; visited[temp]=1; } } } void solve(int T)//我这里是用组合解决的,虽然提交了之后发现用组合比用背包时间还少 { //但是觉得可能是测试数据的原因,个人觉得还是背包靠谱些 printf("Scenario #%d:\n",T); int temp[1500],t,res=0,x; int i,j,max=0,flag=0; int visited[1500]; all=2;total[1]=0; for(i=1;i<=n;i++) max=max+(1<<(i-1)); while(1) { res++;t=1; memset(visited,0,sizeof(visited)); for(i=1;i<all;i++) { // int kao=0; //kao++; for(j=1;j<num;j++) { x=(total[i]|st[j]); if(x==max) { flag=1; break; } if(visited[x]==0) { visited[x]=1; temp[t++]=x; } } if(flag==1) break; } if(flag==1) break; for(i=1;i<t;i++) total[i]=temp[i]; all=t; } printf("%d\n",res); } int main() { int i,T,t; scanf("%d",&T); for(t=1;t<=T;t++) { num1=1; num2=1; num=1; scanf("%d%d%d",&n,&sum1,&sum2); for(i=1; i<=n; i++) scanf("%d",&a[i]); dfs(1,1,0,0); dfs(1,2,0,0); hebing(); solve(t); if(t!=T) printf("\n"); } return 0; }
2.背包解决:
代码实现:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int n,sum1,sum2,a[15]; int st1[1500],st2[1500],st[1500],num1,num2,num; int total[1500],all; void dfs(int f,int flag,int x,int s) { int i,j,temp; if(flag==1&&f==n+1) st1[num1++]=x; else if(f==n+1) st2[num2++]=x; if(f>n) return ; temp=1<<(n-f); if(flag==1) { if(s+a[f]<=sum1) dfs(f+1,flag,x+temp,s+a[f]); dfs(f+1,flag,x,s); } else { if(s+a[f]<=sum2) dfs(f+1,flag,x+temp,s+a[f]); dfs(f+1,flag,x,s); } } void hebing() { int i,j,t=2; int visited[1500],temp; memset(visited,0,sizeof(visited)); for(i=1;i<num1;i++) for(j=1;j<num2;j++) { temp=st1[i]|st2[j]; if(visited[temp]==0) { st[num++]=temp; visited[temp]=1; } } } int Min(int x,int y) { return x>y?y:x; } void solve(int T) { printf("Scenario #%d:\n",T); int i,j,dp[1500]; for(i=1;i<(1<<n);i++) dp[i]=100000000; dp[0]=0; for(i=1;i<num;i++) { for(j=(1<<n)-1;j>=0;j--) { if(dp[j]==100000000) continue; if((j&st[i])==0) dp[j|st[i]]=Min(dp[j|st[i]],dp[j]+1); } } printf("%d\n",dp[(1<<n)-1]); } int main() { int i,T,t; scanf("%d",&T); for(t=1;t<=T;t++) { num1=1; num2=1; num=1; scanf("%d%d%d",&n,&sum1,&sum2); for(i=1; i<=n; i++) scanf("%d",&a[i]); dfs(1,1,0,0); dfs(1,2,0,0); hebing(); solve(t); if(t!=T) printf("\n"); } return 0; }
posted on 2013-11-29 19:28 后端bug开发工程师 阅读(288) 评论(0) 编辑 收藏 举报