2021.10.19 (2)
T1:升降梯
Problem:
Nescafe 之塔一共有 N 层,升降梯在每层都有一个停靠点。手柄有 M 个控制槽,第 i 个控制槽旁边标着一个数 Ci,满足 C1<C2<C3<……<CM。如果 Ci>0,表示手柄扳动到该槽时,电梯将上升 Ci 层;如果 Ci<0,表示手柄扳动到该槽时,电梯将下降-Ci 层;并且一定存在一个 Ci=0,手柄最初就位于此槽中。注意升降梯只能在 1~N 层间移动,因此扳动到使升降梯移动到 1 层以下、N 层以上的控制槽是不允许的。
电梯每移动一层,需要花费 2 秒钟时间,而手柄从一个控制槽扳到相邻的槽,需要花费 1 秒钟时间。探险队员现在在 1 层,并且想尽快到达 N 层,他们想知道从 1 层到 N 层至少需要多长时间?
Code:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int st,c[30]; 4 int n,m; 5 int dis[1010][30]; 6 bool vis[1010][30]; 7 struct node{int x,y;}; 8 queue<node> q; 9 int ans=1919810; 10 void spfa(int x){ 11 memset(dis,0x3f,sizeof(dis)); 12 node tmp; 13 tmp.x=1,tmp.y=x; 14 vis[1][x]=1; 15 dis[1][x]=0; 16 q.push(tmp); 17 while(!q.empty()){ 18 node now=q.front(); 19 q.pop(); 20 vis[now.x][now.y]=0; 21 for(int i=1;i<=m;i++){ 22 int xx=now.x+c[i],l=abs(c[i]*2),tu=abs(now.y-i); 23 if(xx<1||xx>n) continue; 24 if(dis[xx][i]>dis[now.x][now.y]+l+tu){ 25 dis[xx][i]=dis[now.x][now.y]+l+tu; 26 if(!vis[xx][i]){ 27 tmp.x=xx; 28 tmp.y=i; 29 q.push(tmp); 30 vis[xx][i]=1; 31 } 32 } 33 } 34 } 35 for(int i=1;i<=m;i++){ 36 ans=min(ans,dis[n][i]); 37 } 38 ans=ans==1919810?-1:ans; 39 } 40 int main(){ 41 scanf("%d%d",&n,&m); 42 for(int i=1;i<=m;i++){ 43 scanf("%d",c+i); 44 if(c[i]==0) st=i; 45 } 46 spfa(st); 47 cout<<ans<<endl; 48 return 0; 49 }
T2:买鱼
Problem:
王伯(不是王婆)退休后开始养鱼。他一早起床就赶去动物园,发现这个世界的鱼真不少,五光十色、色彩斑斓,大的、小的,什么都有。这些鱼实在是太美了,买的人越来越多,湖里的鱼越来越少。没有美丽的鱼哪里有美丽的湖?于是动
物园不得不规定,对于每种鱼,每个人最多可以买一条。并且有些鱼不能一起买的,因为它们之间会相互争斗吞食。
王伯想买尽可能多的鱼,但很可惜,他的资金有限。他冥想苦思,不知道如何是好。请编写一个程序帮助他。如果有多个方案都能买尽可能多的鱼,选择所花资金最多的一个。
Code:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int ans,m,n,co[50]; 4 long long ansb,ansco; 5 long long st[50]; 6 void dfs(int now,int tot,int mon,long long can,long long sta){ 7 if(now==n+1){ 8 if(tot>ans){ 9 ans=tot; 10 ansco=mon; 11 ansb=sta; 12 } 13 else{ 14 if(tot==ans){ 15 if(mon>ansco){ 16 ans=tot; 17 ansco=mon; 18 ansb=sta; 19 } 20 } 21 } 22 return; 23 } 24 if((can&(1<<now))&&mon+co[now]<=m){ 25 long long to=can&(~(1<<now)); 26 to=to&st[now]; 27 dfs(now+1,tot+1,mon+co[now],to,sta|(1<<now)); 28 } 29 dfs(now+1,tot,mon,can,sta); 30 } 31 int main(){ 32 scanf("%d%d",&m,&n); 33 for(int i=1;i<=n;i++){ 34 int x,y; 35 scanf("%d%d",&x,&y); 36 co[x]=y; 37 } 38 for(int i=0;i<=n;i++){ 39 st[i]=(1ll<<(n+1))-1; 40 } 41 int x,y; 42 while(1){ 43 scanf("%d%d",&x,&y); 44 if(x==0&&y==0) break; 45 if(x==0||y==0) continue; 46 st[x]&=~(1<<y); 47 st[y]&=~(1<<x); 48 } 49 dfs(1,0,0,st[0],0); 50 cout<<ans<<" "<<ansco<<endl; 51 for(int i=1;i<=n;i++){ 52 if(ansb&(1<<i)){ 53 cout<<i<<endl; 54 } 55 } 56 return 0; 57 }
T3:登山
Problem:
Freda 和 rainbow 只好花钱让它们坐索道下山。索道上的缆车最大承重量为W,而 N 只小猫的重量分别是 C1、C2……CN。当然,每辆缆车上的小猫的重量之和不能超过 W。每租用一辆缆车,Freda 和 rainbow 就要付 1 美元,所以他们想知道,最少需要付多少美元才能把这 N 只小猫都运送下山?
Code:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,w; 4 struct state{ 5 int c,s; 6 }all[530000]; 7 queue<int >q; 8 int wight[20]; 9 int vis[530000],init[530000]; 10 int main(){ 11 scanf("%d%d",&n,&w); 12 for(int i=1;i<=n;++i) scanf("%d",&wight[i]); 13 int nd=(1<<(n+1))-1; 14 q.push(nd); 15 vis[nd]=1; 16 init[nd]=1; 17 all[nd].c=1; 18 all[nd].s=w; 19 while(!q.empty()){ 20 int now=q.front(); 21 init[now]=0; 22 q.pop(); 23 for(int i=1;i<=n;++i){ 24 if(now&1<<i){ 25 int to=now^(1<<i); 26 int totot=all[now].c,tore=all[now].s; 27 if(tore<wight[i]){ 28 totot++; 29 tore=w-wight[i]; 30 } 31 else tore-=wight[i]; 32 if(vis[to]){ 33 if(totot>all[to].c) continue; 34 if(totot==all[to].c){ 35 if(tore<all[to].s) continue; 36 } 37 } 38 else vis[to]=1; 39 all[to].c=totot; 40 all[to].s=tore; 41 if(!init[to]){ 42 q.push(to); 43 init[to]=1; 44 } 45 } 46 } 47 } 48 printf("%d",all[1].c); 49 return 0; 50 }