过河问题引发--无策略的暴搜与有策略的动归
在一个月黑风高的夜晚,有一群人在河的左岸,想通过唯一的一根独木桥走到河的右岸。在这伸手不见五指的黑夜里,过桥时必须借助灯光来照明,很不幸的是,他们只有一盏灯。另外,独木桥上最多承受两个人同时经过,否则将会坍塌。每个人单独过桥都需要一定的时间,不同的人需要的时间可能不同。两个人一起过桥时,由于只有一盏灯,所以需要的时间是较慢的那个人单独过桥时所花的时间。现输入n和这n个人单独过桥时需要的时间,请计算总共最少需要多少时间,他们才能全部到达河的右岸?
注意:当灯被带到河的右岸,需要由一人把灯带回左岸,以便左岸的其他人通过,这个人可以交给左岸的任意两个人让他们通过独木桥
#include<iostream> using namespace std; #define N 21 const int INF=10000;//花费时间不可能为INF const int LEFT=0; const int RIGHT=1; const int LEFT_TO_RIGHT=0; const int RIGHT_TO_LEFT=1; int time[N]; int pos[N]; int n,ans; //暴力搜素的回溯解法 //无脑地让任意两个人去左岸,让任意一个人回到右岸,只需要枚举所有可选人即可 int dfs(int stage){ if(stage==LEFT_TO_RIGHT){ int num=0,res=0; for(int i=1;i<=n;i++){ if(pos[i]==LEFT){ num++; if(time[i]>res)res=time[i]; } } if(num==2)return res; res=INF; for(int i=1;i<n;i++) if(pos[i]==LEFT) for(int j=i+1;j<=n;j++) if(pos[j]==LEFT){ pos[i]=RIGHT; pos[j]=RIGHT; res=min(res,max(time[i],time[j])+dfs(RIGHT_TO_LEFT)); pos[i]=LEFT; pos[j]=LEFT; } return res; } else if(stage==RIGHT_TO_LEFT){ int res=INF; for(int i=1;i<=n;i++) if(pos[i]==RIGHT){ pos[i]=LEFT; res=min(res,time[i]+dfs(LEFT_TO_RIGHT)); pos[i]=RIGHT; } return res; } } int main(){ cin>>n; for(int i=1;i<=n;i++)cin>>time[i]; if(n==1){//特判 cout<<time[1]; return; } //不用初始化pos数组,数组值默认为0,即在左边 ans=dfs(LEFT_TO_RIGHT); cout<<ans; return 0; }
#include<iostream> #include<algorithm> using namespace std; int dp[105]; int n; int time[105]; int main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>time[i]; } sort(time+1,time+1+n); dp[2]=time[2]; dp[3]=time[2]+time[1]+time[3]; for(int i=4;i<=n;i++){ dp[i]=dp[i-2]+2*time[2]+time[1]+time[i]; } cout<<dp[n]; return 0; }
浙公网安备 33010602011771号