Topcoder SRM 146 Div2 1000(dfs搜索,经典过桥问题,很有意思)

Problem Statement

 

A well-known riddle goes like this: Four people are crossing an old bridge. The bridge cannot hold more than two people at once. It is dark, so they can't walk without a flashlight, and they only have one flashlight! Furthermore, the time needed to cross the bridge varies among the people in the group. For instance, let's say that the people take 1, 2, 5 and 10 minutes to cross the bridge. When people walk together, they always walk at the speed of the slowest person. It is impossible to toss the flashlight across the bridge, so one person always has to go back with the flashlight to the others. What is the minimum amount of time needed to get all the people across the bridge?

In this instance, the answer is 17. Person number 1 and 2 cross the bridge together, spending 2 minutes. Then person 1 goes back with the flashlight, spending an additional one minute. Then person 3 and 4 cross the bridge together, spending 10 minutes. Person 2 goes back with the flashlight (2 min), and person 1 and 2 cross the bridge together (2 min). This yields a total of 2+1+10+2+2 = 17 minutes spent.

You want to create a computer program to help you solve new instances of this problem. Given an vector <int>times, where the elements represent the time each person spends on a crossing, your program should return the minimum possible amount of time spent crossing the bridge.

Definition

 
Class:BridgeCrossing
Method:minTime
Parameters:vector <int>
Returns:int
Method signature:int minTime(vector <int> times)
(be sure your method is public)

Limits

 
Time limit (s):2.000
Memory limit (MB):64

Notes

-In an optimal solution, exactly two people will be sent across the bridge with the flashlight each time (if possible), and exactly one person will be sent back with the flashlight each time. In other words, in an optimal solution, you will never send more than one person back from the far side at a time, and you will never send less than two people across to the far side each time (when possible).

Constraints

-times will have between 1 and 6 elements, inclusive.
-Each element of times will be between 1 and 100, inclusive.

Examples

0) 
 
{ 1, 2, 5, 10 }
Returns: 17
The example from the text.
1) 
 
{ 1, 2, 3, 4, 5 }
Returns: 16
One solution is: 1 and 2 cross together (2min), 1 goes back (1min), 4 and 5 cross together (5min), 2 goes back (2min), 1 and 3 cross together (3min), 1 goes back (1min), 1 and 2 cross together (2min). This yields a total of 2 + 1 + 5 + 2 + 3 + 1 + 2 = 16 minutes spent.
2) 
 
{ 100 }
Returns: 100
Only one person crosses the bridge once.
3) 
 
{ 1, 2, 3, 50, 99, 100 }
Returns: 162

很经典的一个过桥问题

之前在思维训练题目中还见到过一样的题,没想到直接成为了一道tc题= =

当时还想了很久呢,现在才发现,首先不能贪心,任何直接贪心做出来的都基本上会wrong的,不信你去试试(=。=!)。

反正数据范围是6,就用dfs搜索办法,最关键的地方是,每次从对岸选取一个人返回的时候,都要选取过桥时间最少的那个!并且注意最后一趟,2个人过去了后,就不需要返回了.

这里的dfs不是很好写,反反复复弄了好久才弄出来,建议不要看我代码,还是自己写出来比较好,毕竟我写的有点乱。

//Hello. I'm Peter.
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double ld;
#define peter cout<<"i am peter"<<endl
#define input freopen("data.txt","r",stdin)
#define randin srand((unsigned int)time(NULL))
#define INT (0x3f3f3f3f)*2
#define LL (0x3f3f3f3f3f3f3f3f)*2
#define gsize(a) (int)a.size()
#define len(a) (int)strlen(a)
#define slen(s) (int)s.length()
#define pb(a) push_back(a)
#define clr(a) memset(a,0,sizeof(a))
#define clr_minus1(a) memset(a,-1,sizeof(a))
#define clr_INT(a) memset(a,INT,sizeof(a))
#define clr_true(a) memset(a,true,sizeof(a))
#define clr_false(a) memset(a,false,sizeof(a))
#define clr_queue(q) while(!q.empty()) q.pop()
#define clr_stack(s) while(!s.empty()) s.pop()
#define rep(i, a, b) for (int i = a; i < b; i++)
#define dep(i, a, b) for (int i = a; i > b; i--)
#define repin(i, a, b) for (int i = a; i <= b; i++)
#define depin(i, a, b) for (int i = a; i >= b; i--)
#define pi 3.1415926535898
#define eps 1e-6
#define MOD 1000000007
#define MAXN 100100
#define N
#define M 200
int ans;
struct Digit
{
    int id;
    int times;
}d,d1,d2,back;
Digit chooseone(vector<Digit>there)
{
    int len=gsize(there);
    int mini=INT;
    Digit res;
    rep(i,0,len)
    {
        if(mini>there[i].times)
        {
            mini=there[i].times;
            res=there[i];
        }
    }
    return res;
}
void dfs(vector<Digit>here,vector<Digit>there,int totaltime)
{
    int len1=gsize(here);
    if(len1<=2)
    {
        totaltime+=max(here[0].times,here[1].times);
        ans=min(ans,totaltime);
        return;
    }
    int newtotaltime;
    rep(i,0,len1)
    {
        rep(j,i+1,len1)
        {
            d1=here[i];
            d2=here[j];
            newtotaltime=totaltime;
            newtotaltime+=max(d1.times,d2.times);
            vector<Digit>newtheretemp;
            newtheretemp.clear();
            int len2=gsize(there);
            rep(k,0,len2)
            {
                d=there[k];
                newtheretemp.pb(d);
            }
            newtheretemp.pb(d1);
            newtheretemp.pb(d2);
            back=chooseone(newtheretemp);
            newtotaltime+=back.times;
            vector<Digit>newthere;
            newthere.clear();
            len2=gsize(newtheretemp);
            rep(k,0,len2)
            {
                d=newtheretemp[k];
                if(d.id!=back.id) newthere.pb(d);
            }
            //for here
            vector<Digit>newhere;
            newhere.clear();
            rep(k,0,len1)
            {
                d=here[k];
                if(d.id!=d1.id && d.id!=d2.id) newhere.pb(d);
            }
            newhere.pb(back);
            dfs(newhere,newthere,newtotaltime);
        }
    }
}
class BridgeCrossing
{
public:
    int minTime(vector <int> times)
    {
        ans=INT;
        int len=gsize(times);
        if(len==1)
        {
            ans=min(ans,times[0]);
        }
        else
        {
            vector<Digit>there;
            there.clear();
            vector<Digit>here;
            rep(i,0,len)
            {
                d.id=i;
                d.times=times[i];
                here.pb(d);
            }
            dfs(here,there,0);
        }
        return ans;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值