Fancy Antiques(NAIPC 2016) 爆搜
阿新 • • 發佈:2018-12-13
題意:
選擇最多k個商店,買n個物品,求最小花費是多少。
思路:
看的題解,急著走,先不自己寫了。
這個人的剪枝方法的奇妙之處在於,先將商店排序,買的貴的先dfs。
1.通過提前求出,從當前這個商店直到後面的商店,每件物品的最小花費可以是多少,如果當前最小花費已經大於最優值,或者無法獲得,那直接結束。
2.商店數超過k則結束。
就是那樣一個排序後的dfs順序,和加上minv陣列提前預判,就可以讓這個題目爆過去,真的很神奇。
還是太菜了。
程式碼:
#include <bits/stdc++.h> using namespace std ; typedef pair < int, int > pii ; #define clr( a , x ) memset ( a , x , sizeof a ) const int MAXN = 105 ; const int INF = 0x3f3f3f3f ; struct Node { vector < pii > G ; int val ; //這個順序,先搜大的,minv bool operator < ( const Node& a ) const { return val > a.val ; } } ; Node a[MAXN] ; int minv[MAXN][MAXN] ; int pre[MAXN] ; int tmp[MAXN][MAXN] ; int ans ; int n, m, k ; void dfs ( int cur, int num ) { int val = 0 ; for ( int i = 1 ; i <= n ; ++ i ) { if (pre[i] == INF) { val = INF ; break ; } val += pre[i] ; } if ( val < ans ) ans = val ; //超過k則返回 if ( num >= k ) return ; int tot = 0 ; //很重要的剪枝,如果後面沒有更優的,那沒有必要再搜尋下去 for ( int i = 1 ; i <= n ; ++ i ) { if ( pre[i] == INF && minv[cur][i] == INF ) return ; tot += min ( pre[i], minv[cur][i] ) ; if ( tot >= ans ) return ; } for ( int i = cur ; i <= m ; ++ i ) { for ( int j = 1 ; j <= n ; ++ j ) { tmp[num][j] = pre[j] ; } for ( int j = 0 ; j < a[i].G.size () ; ++ j ) { int x = a[i].G[j].first ; pre[x] = min (pre[x], a[i].G[j].second) ; } dfs ( i + 1, num + 1 ) ; for ( int j = 1 ; j <= n ; ++ j ) { pre[j] = tmp[num][j] ; } } } void solve () { ans = INF ; for ( int i = 1 ; i <= m ; ++ i ) { a[i].G.clear () ; a[i].val = 0 ; } for ( int i = 1 ; i <= n ; ++ i ) { int x, p, y, q ; scanf ( "%d%d%d%d", &x, &p, &y, &q ) ; a[x].val ++ ; a[y].val ++ ; if ( p < q ) a[x].val += 2 ; else a[y].val += 2 ; a[x].G.push_back ( pii ( i, p ) ) ; a[y].G.push_back ( pii ( i, q ) ) ; } sort ( a + 1, a + m + 1 ) ; for ( int i = 1 ; i <= n ; ++ i ) { minv[m + 1][i] = INF ; pre[i] = INF ; } for ( int i = m ; i >= 1 ; -- i ) { for ( int j = 1 ; j <= n ; ++ j ) { minv[i][j] = minv[i + 1][j] ; } for ( int j = 0 ; j < a[i].G.size () ; ++ j ) { int x = a[i].G[j].first, v = a[i].G[j].second ; minv[i][x] = min ( minv[i][x], v ) ; } } dfs ( 1, 0 ) ; printf ( "%d\n", ans == INF ? -1 : ans ) ; } int main () { while ( ~scanf ( "%d%d%d", &n, &m, &k ) ) solve () ; return 0 ; }