NOIP 2017 宝藏 (状压,搜索)

来源:互联网 发布:怎么查看淘宝注册日期 编辑:程序博客网 时间:2024/04/30 11:21

Description

参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的 m 条道路和它们的长度。小明决心亲自前往挖掘所有宝藏屋中的宝藏。但是,每个宝藏屋距离地面都很远, 也就是说,从地面打通一条到某个宝藏屋的道路是很困难的,而开发宝藏屋之间的道路 则相对容易很多。
小明的决心感动了考古挖掘的赞助商,赞助商决定免费赞助他打通一条从地面到某 个宝藏屋的通道,通往哪个宝藏屋则由小明来决定。在此基础上,小明还需要考虑如何开凿宝藏屋之间的道路。已经开凿出的道路可以 任意通行不消耗代价。每开凿出一条新道路,小明就会与考古队一起挖掘出由该条道路 所能到达的宝藏屋的宝藏。另外,小明不想开发无用道路,即两个已经被挖掘过的宝藏 屋之间的道路无需再开发。新开发一条道路的代价是:L×K
L代表这条道路的长度,K代表从赞助商帮你打通的宝藏屋到这条道路起点的宝藏屋所经过的 宝藏屋的数量(包括赞助商帮你打通的宝藏屋和这条道路起点的宝藏屋) 。
请你编写程序为小明选定由赞助商打通的宝藏屋和之后开凿的道路,使得工程总代 价最小,并输出这个最小值。

Solution

n只有12,考虑状压,直接搜索即可。
没错这道题就是这么简单,
没错我考试时就是这么智障。。

Code

#include<bits/stdc++.h>using namespace std;typedef long long ll;typedef pair<int, int> PII;typedef vector<int> VI;#define For(i , j , k) for (register int i = (j) , i##_end_ = (k) ; i <= i##_end_ ; ++ i)#define Fordown(i , j , k) for (register int i = (j) , i##_end_ = (k) ; i >= i##_end_ ; -- i)#define Set(a , b) memset(a , b , sizeof(a))#define pb(a) push_back(a)#define mp(a, b) make_pair(a, b)#define ALL(a) (a).begin(), (a).end()#define SZ(a) ((int)(a).size())#define fir first#define sec second#define INF (0x3f3f3f3f)#define INF1 (2139062143)#define Mod (1000000007)#ifdef hany01#define debug(...) fprintf(stderr , __VA_ARGS__)#else#define debug(...)#endiftemplate <typename T> inline bool chkmax(T &a , T b) { return a < b ? (a = b , 1) : 0; }template <typename T> inline bool chkmin(T &a , T b) { return b < a ? (a = b , 1) : 0; }int _ , __;char c_;inline int read(){    for (_ = 0 , __ = 1 , c_ = getchar() ; !isdigit(c_) ; c_ = getchar()) if (c_ == '-') __ = -1;    for ( ; isdigit(c_) ; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48);    return _ * __;}inline void File(){#ifdef hany01    freopen("treasure.in" , "r" , stdin);    freopen("treasure.out" , "w" , stdout);#endif}const int maxn = 12;int n, m, w[maxn + 3][maxn + 3], FULL, dis[maxn];ll f[1 << maxn], Ans;inline void Input(){    int uu, vv, ww;    n = read(); m = read();    Set(w, 127);    For(i, 1, m) uu = read(), vv = read(), ww = read(), chkmin(w[uu][vv], ww), chkmin(w[vv][uu], ww);    FULL = (1 << n) - 1;}void dfs(int cdt){    For(u, 1, n)    {        if (!((1 << (u - 1)) & cdt)) continue;        For(v, 1, n)        {            if (((1 << (v - 1)) & cdt) || w[u][v] == INF1) continue;            if (chkmin(f[cdt | (1 << (v - 1))], f[cdt] + dis[u] * w[u][v]))            {                register int tmp = dis[v];                dis[v] = dis[u] + 1;                dfs(cdt | (1 << (v - 1)));                dis[v] = tmp;            }        }    }}inline void Solve(){    Ans = 9999999999999ll;    For(i, 1, n)    {        Set(dis, 127); Set(f, 127);        dis[i] = 1; f[1 << (i - 1)] = 0;        dfs(1 << (i - 1));        chkmin(Ans, f[FULL]);    }    cout << Ans << endl;}int main(){    File();    Input();    Solve();    return 0;}//细草穿沙雪半销,吴宫烟冷水迢迢。//梅花竹里无人见,一夜吹香过石桥。//--姜夔《除夜自石湖归苕溪》其一
原创粉丝点击