http://acm.hdu.edu.cn/showproblem.php?pid=4848

题意:求遍历所有点的最小值(这个答案是加i点到起始点的距离,不是当前点到i的距离),必须在ti[i]前到达i点

题解:暴搜,剪枝是((当前值>ans)&&(当前点到未到点的时间加上起点到当前点的时间大于未到点的截止时间))则停止,遍历到n个点停止搜索,各点间的最短路用floyd处理

思考:用暴搜贼简单的一道题,难在勇于暴搜的那份勇气,比赛的时候我们根本没读这道题也没有什么好说的了

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std ;
const int INF=0xfffffff ;
int n ;
int dis[55][55],ti[55],vis[55],ans ;

void floyd()
{
    for(int k=0 ;k<n ;k++)
    {
        for(int i=0 ;i<n ;i++)
        {
            for(int j=0 ;j<n ;j++)
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]) ;
        }
    }
}

void dfs(int now,int s,int t,int sum)
{
    if(s==n)
    {
        ans=min(ans,sum) ;
        return ;
    }
    if(sum>ans)return ;
    for(int i=1 ;i<n ;i++)
        if(!vis[i] && dis[now][i]+t>ti[i])return ;
    for(int i=1 ;i<n ;i++)
    {
        if(!vis[i])
        {
            vis[i]=1 ;
            dfs(i,s+1,t+dis[now][i],sum+dis[now][i]*(n-s)) ;
            vis[i]=0 ;
        }
    }
}

int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=0 ;i<n ;i++)
            for(int j=0 ;j<n ;j++)
                scanf("%d",&dis[i][j]) ;
        for(int i=1 ;i<n ;i++)
            scanf("%d",&ti[i]) ;
        floyd() ;
        ans=INF ;
        memset(vis,0,sizeof(vis)) ;
        dfs(0,1,0,0) ;
        if(ans==INF)puts("-1") ;
        else printf("%d\n",ans) ;
    }
    return 0 ;
}
View Code