hdu 3810 超大容量背包(n=50不是40)

来源:互联网 发布:知与行杂志版面费 编辑:程序博客网 时间:2024/06/06 02:56

先贴一个挑战上解决n=40时的超大容量背包,不过解决n=50时会TLE和MLE

#include<cstdio>#include<cstring>#include<vector>#include<algorithm>#define MIN(x,y) ((x)>(y)?(y):(x))using namespace std;const long long INF=5010000000000;vector<int>Q[100];pair<int,int>ps[1<<21];int map[60][60];int vis[60];long long int w[60],v[60];int cnt,n,tot;long long m; void dfs(int x){vis[x]=1;Q[cnt].push_back(x);for(int i=1;i<=n;i++){if(map[x][i]&&!vis[i])dfs(i);}}void divid(){cnt=0;memset(vis,0,sizeof(vis));for(int i=1;i<=n;i++)    {    if(!vis[i])    {    Q[cnt].clear();    dfs(i);    cnt++;}}}int find(int x){int l=0,r=tot;while(l<r){int mid=(l+r)>>1;if(ps[mid].first+x<m)l=mid+1;elser=mid;}return l;}long long  solve(int x){int n2=Q[x].size()/2;if(n2>21)n2=21; for(int i=0;i<1<<n2;i++){long long int sw=0;long long int sv=0;for(int j=0;j<n2;j++){if(i>>j&1){sw+=w[Q[x][j]];sv+=v[Q[x][j]];}}ps[i]=make_pair(sw,sv);}sort(ps,ps+(1<<n2));tot=1;for(int i=1;i<1<<n2;i++){if(ps[tot-1].second<ps[i].second)ps[tot++]=ps[i];}//printf("n2=%d tot=%d\n",n2,tot);//for(int i=0;i<tot;i++)//printf("first=%d second=%d\n",ps[i].first,ps[i].second); long long int res=INF;for(int i=0;i<1<<(Q[x].size()-n2);i++){long long int sw=0,sv=0;for(int j=0;j<Q[x].size()-n2;j++){if(i>>j&1){sw+=w[Q[x][n2+j]];sv+=v[Q[x][n2+j]];}}if(sv<res){int lo=find(sw);if(lo!=tot) res=MIN(res,sv+ps[lo].second);}}return res;} long long int cal(){long long int res,t;res=INF;for(int i=0;i<cnt;i++){t=solve(i);if(t<res)res=t;}return res;}int main(){int T,z=1;scanf("%d",&T);while(T--){scanf("%d%lld",&n,&m);//printf("n=%d m=%d \n ",n,m); memset(map,0,sizeof(map));for(int i=1;i<=n;i++){int t;scanf("%lld%lld%d",&v[i],&w[i],&t);while(t--){int x;scanf("%d",&x);map[i][x]=map[x][i]=1;}}//for(int i=1;i<=n;i++)//printf("v=%d w=%d\n",v[i],w[i]); //for(int i=1;i<=n;i++)//{//for(int j=1;j<=n;j++)//printf("%d ",map[i][j]);//printf("\n");//} divid(); //printf("cnt=%d\n",cnt);//for(int i=0;i<cnt;i++)///{//printf("size=%d\n",Q[i].size()); //for(int j=0;j<Q[i].size();j++)//printf("%d ",Q[i][j]);//printf("\n\n");//}long long int res=cal();if(res==INF)printf("Case %d: Poor Magina, you can't save the world all the time!\n",z++);elseprintf("Case %d: %lld\n",z++,res); }}


下面是用队列模拟。。。

#include<cstdio>#include<cstring>#include<queue>#include<vector>#define INF 500000010#define MIN(x,y) ((x)>(y)?(y):(x))using namespace std;int n,cnt,vis[60],map[60][60];long long m,v[60],w[60];vector<int>Q[60];struct node{long long v,w;bool operator<(const node a)const{if(w!=a.w)return w<a.w;elsereturn v>a.v;}};void dfs(int x){vis[x]=1;Q[cnt].push_back(x);for(int i=1;i<=n;i++)if(map[x][i]&&!vis[i])dfs(i);}void init(){cnt=0;memset(vis,0,sizeof(vis));for(int i=1;i<=n;i++)if(!vis[i]){Q[cnt].clear();dfs(i);cnt++;}}long long cal(){long long res=INF;priority_queue<node>q1,q2;node s; for(int i=0;i<cnt;i++){while(!q1.empty())q1.pop();while(!q2.empty())q2.pop();s.v=s.w=0; q1.push(s);for(int j=0;j<Q[i].size();j++){while(!q1.empty()){s=q1.top();q1.pop();q2.push(s);s.v+=v[Q[i][j]];s.w+=w[Q[i][j]];if(s.w>=m){res=MIN(res,s.v);continue;}if(s.v>=res)continue;q2.push(s);}long long temp=INF;while(!q2.empty()){s=q2.top();q2.pop();if(s.v<temp){temp=s.v;q1.push(s);}}}} return res;}int main(){int T,lo=1;scanf("%d",&T);while(T--){scanf("%d%lld",&n,&m);memset(map,0,sizeof(map));for(int i=1;i<=n;i++){int t;scanf("%lld%lld%d",&v[i],&w[i],&t);while(t--){int x;scanf("%d",&x);map[i][x]=map[x][i]=1; }}init();long long res=cal();if(res==INF)printf("Case %d: Poor Magina, you can't save the world all the time!\n",lo++);elseprintf("Case %d: %d\n",lo++,res);} }





0 0
原创粉丝点击