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

比赛的时候我甚至没看这道题,事实上不难....

可是说实话,如今对题意还是理解不太好......

犯的错误:

1、floy循环次序写错,

2、搜索的时候。应该先推断i是不是能够搜(就是可不可能产生解)。然后标记vis[i]=1。我二逼的先标记vis[i]=1,然后推断i是不是可搜,这样肯定会导致有些时候,cnt!=n

我的剪枝方法(2546MS AC):

搜下一个结点之前。确保时间小于全部的未訪问的结点的Deadline

//#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std; #define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define ull unsigned long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdout)
const ll ll_INF = ((ull)(-1))>>1;
const double EPS = 1e-8;
const int INF = 1e9+7;
const int MAXN = 50; int n;
int mat[MAXN][MAXN];
int dis[MAXN][MAXN];
int dead[MAXN];
void floy()
{
repe(k,1,n)
for(int i=1;i<=n;i++)
repe(j,1,n) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
int ans;
int vis[MAXN]; void dfs(int u, int t, int cnt,int tmp)
{
if(dead[u]<t || tmp>ans)return;
if(cnt == n)
{
ans=min(ans,tmp);
return;
}
for(int i=2;i<=n;i++)
if(!vis[i] && dead[i]>=t+dis[u][i])
{
int flag=0;
for(int j=2;j<=n;j++)
if(!vis[j] && t+dis[u][i]>dead[j] && i!=j)
flag=1;
if(flag)continue;
vis[i]=1;
dfs(i,t+dis[u][i],cnt+1,tmp+dis[u][i]*(n-cnt));
vis[i]=0;
}
} int main()
{
//IN("hdu4848.txt");
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&mat[i][j]),dis[i][j]=mat[i][j];
floy();
dead[1]=INF;
repe(i,2,n)
scanf("%d",&dead[i]);
ans=INF;
CL(vis,0);
vis[1]=1;
dfs(1,0,1,0);
if(ans == INF)printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}

网上的方法:(359ms AC)

事实上剪枝思路跟我一样,可是比我的更好

倘若搜到当前结点,检查全部的未訪问的结点,假设不管以哪个未訪问结点为起点都不可能得到解,直接返回,相当于比我少遍历一层并且少了非常多反复

//#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std; #define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define ull unsigned long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdout)
const ll ll_INF = ((ull)(-1))>>1;
const double EPS = 1e-8;
const int INF = 1e9+7;
const int MAXN = 50; int n;
int mat[MAXN][MAXN];
int dis[MAXN][MAXN];
int dead[MAXN]; void floy()
{
repe(k,1,n)
for(int i=1;i<=n;i++)
repe(j,1,n) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
int ans;
int vis[MAXN]; void dfs(int u, int t, int cnt,int tmp)
{
if(dead[u]<t || tmp>ans)return;
if(cnt == n)
{
ans=min(ans,tmp);
return;
}
for(int i=2;i<=n;i++)
if(!vis[i] && t+dis[u][i]>dead[i])
return;
for(int i=2;i<=n;i++)
if(!vis[i] && dead[i]>=t+dis[u][i])
{
vis[i]=1;
dfs(i,t+dis[u][i],cnt+1,tmp+dis[u][i]*(n-cnt));
vis[i]=0;
}
} int main()
{
//IN("hdu4848.txt");
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&mat[i][j]),dis[i][j]=mat[i][j];
floy();
dead[1]=INF;
repe(i,2,n)
scanf("%d",&dead[i]);
ans=INF;
CL(vis,0);
vis[1]=1;
dfs(1,0,1,0);
if(ans == INF)printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}

hdu 4848 搜索+剪枝 2014西安邀请赛的更多相关文章

  1. hdu 5887 搜索+剪枝

    Herbs Gathering Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  2. poj 1198 hdu 1401 搜索+剪枝 Solitaire

    写到一半才发现能够用双向搜索4层来写,但已经不愿意改了,干脆暴搜+剪枝水过去算了. 想到一个非常水的剪枝,h函数为  当前点到终点4个点的最短距离加起来除以2.由于最多一步走2格,然后在HDU上T了, ...

  3. hdu 6196 搜索+剪枝

    Today, Bob plays with a child. There is a row of n numbers. One can takes a number from the left sid ...

  4. hdu 5113(2014北京—搜索+剪枝)

    题意:有N*M的棋盘,用K种颜色去染,要求相邻块不能同色.已知每种颜色要染的块数,问能不能染,如果能,输出任一种染法. 最开始dfs失败了- -,优先搜索一行,搜完后进入下一列,超时.本来以为搜索不行 ...

  5. hdu 5469 Antonidas(树的分治+字符串hashOR搜索+剪枝)

    题目链接:hdu 5469 Antonidas 题意: 给你一颗树,每个节点有一个字符,现在给你一个字符串S,问你是否能在树上找到两个节点u,v,使得u到v的最短路径构成的字符串恰好为S. 题解: 这 ...

  6. 计蒜客 39272.Tree-树链剖分(点权)+带修改区间异或和 (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest E.) 2019ICPC西安邀请赛现场赛重现赛

    Tree Ming and Hong are playing a simple game called nim game. They have nn piles of stones numbered  ...

  7. NOIP2015 斗地主(搜索+剪枝)

    4325: NOIP2015 斗地主 Time Limit: 30 Sec  Memory Limit: 1024 MBSubmit: 270  Solved: 192[Submit][Status] ...

  8. hdu 5016 点分治(2014 ACM/ICPC Asia Regional Xi'an Online)

    Mart Master II Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  9. hdu 5636 搜索 BestCoder Round #74 (div.2)

    Shortest Path  Accepts: 40  Submissions: 610  Time Limit: 4000/2000 MS (Java/Others)  Memory Limit: ...

随机推荐

  1. ASP.NET-FineUI开发实践-6(三)

    自动补全也算是好东西吧,我也不清楚下拉列表可以过滤为啥还有自动补全,其实自动补全用到还是通过jq获取服务端的动态数据补全.我没做动态的例子,其实好写,就不写了. 1.用到了两个js包 <scri ...

  2. POJ2449

    #include<stdio.h> #include<iostream> #include<queue> #include<vector> using ...

  3. svg学习笔记

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  4. Jsp笔记(1)

    1. jsp页面中出现中文乱码怎么解决? <%@ page contentType="text/html; charset=GB2312"%> <%@ page ...

  5. IPTV中的EPG前端优化

    先看一下IPTV相关情况: l 目前TPTV市场情况 a) 截止今年2月,全国IPTV总用户数达3630.2万,我国移动互联网用户规模接近9亿,人均月接入量近300M,8M宽带达半数,光纤近4成. 图 ...

  6. JAVA-2-GetDay

    import java.util.*; public class Ch0310 { public static void main(String[] args) { // TODO 自动生成的方法存根 ...

  7. MySQL是否在扫描额外的记录

    在确定查询只是返回需要的数据之后,接下来应该看看查询为了返回结果是否扫描了过多的数据.对于MySQL,最简单的衡量查询开销的三个指标如下: 1响应时间,2扫描行数,3返回行数 没有那个指明能够完美的衡 ...

  8. Nginx log

    ngx_http_log_module 模块通过指定的格式把请求写入日志.请求登陆到location处理结束的环境中.如果重定向发生在请求处理过程中,这或许与location原理不同. Example ...

  9. li的border无法和上边对齐

    如果利用border设置四周的border,如果一边的边框比较长无法对齐 解决办法: .test{ position: relative; border: 1px solid #808080; hei ...

  10. mysql命令行执行外部文件

    mysql命令行执行外部文件