NOIP2018提高組省一衝獎班模測訓練(一)
阿新 • • 發佈:2018-11-08
比賽連結
https://www.51nod.com/contest/problemList.html#!contestId=72&randomCode=147206
這次考試的題非常有質量
這次考試暴露了非常多的問題,心理給自己設限,知識點不熟練等等問題。
只拿了暴力的分。
奈芙蓮的護符
這道題複習狀壓dp,狀壓dp一般可以處理一個集合內的問題
這道題是第三題,但我放在這一題
因為這一題反而最水……
我當時一看到資料範圍20,馬上想到狀壓dp
但是一方面因為覺得這是第三題,應該會比較難,而且前面兩道題都做不出來,所以心理障礙
很大,就沒有怎麼很深入的去想(不過說到底還是狀壓dp不熟練
考完後,5分鐘秒了,發現這是我做過最水的狀壓dp題。
這道題和TSP問題很類似(不懂的可以百度一下,或者我部落格裡面有)
用1表示魔力還在,0表示沒有了。
那麼dp[S] = min(dp[S], dp[S^(1<<j)] + c[j][i])
#include<bits/stdc++.h> #define REP(i, a, b) for(register int i = (a); i < (b); i++) #define _for(i, a, b) for(register int i = (a); i <= (b); i++) usingnamespace std; const int MAXM = (1 << 20) + 10; const int MAXN = 30; int c[MAXN][MAXN], dp[MAXM]; int num(int x) { return !x ? 0 : 1 + num(x & (x - 1)); } //二進位制中1的個數 int main() { int n, k; scanf("%d%d", &n, &k); REP(i, 0, n) REP(j, 0, n) scanf("%d", &c[i][j]); int ans = 1e9; memset(dp, 0x3f, sizeof(dp)); //這裡初始化要注意 dp[(1<<n)-1] = 0; for(register int S = (1 << n) - 1; S >= 0; S--) { if(num(S) < k) continue; REP(i, 0, n) if(S & (1 << i)) REP(j, 0, n) if(!(S & (1 << j))) dp[S] = min(dp[S], dp[S^(1<<j)] + c[j][i]); if(num(S) == k) ans = min(ans, dp[S]); } printf("%d\n", ans); return 0; }
奈芙蓮的序列
這是第二題。我覺得第一題才是最難的,最後講