过河问题引发--无策略的暴搜与有策略的动归

在一个月黑风高的夜晚,有一群人在河的左岸,想通过唯一的一根独木桥走到河的右岸。在这伸手不见五指的黑夜里,过桥时必须借助灯光来照明,很不幸的是,他们只有一盏灯。另外,独木桥上最多承受两个人同时经过,否则将会坍塌。每个人单独过桥都需要一定的时间,不同的人需要的时间可能不同。两个人一起过桥时,由于只有一盏灯,所以需要的时间是较慢的那个人单独过桥时所花的时间。现输入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;
}

 

 

posted on 2020-03-31 11:12  ~明月几时有  阅读(221)  评论(0)    收藏  举报