水題
有15本書,和15個**,你要分配這15個**,使得總價最小.
此外,有一些**方案,每個方案是一些書的集合,表示只要買全了這個方案的書,則最便宜的一本書免費
你最後選擇的所有方案不能有重複的書.
第一感覺就是狀壓dp 了
首先二進位制列舉子集,對於每個當前狀態,考慮可以從哪些狀態轉移過來,這時候再列舉他的子集,
時間複雜度看起來是$2^n * 2^n $ 實際上是3
n3^n
3n,寫法:
for
(int sta=
1;sta<(1
<;++sta)
}
時間複雜度分析:cn1
21+c
n22n
+cn3
23+.
..+c
nn2n
=(2+
1)n=
3n
c_n^12^1 + c_n^22^n + c_n^32^3 + ...+c_n^n2^n = (2+1)^n = 3^n
cn121
+cn2
2n+
cn3
23+.
..+c
nn2
n=(2
+1)n
=3n具體轉移,考慮當前列舉的子集是否是某個**方案,
如果不是,直接轉移,很自然
如果是,這個時候,考慮能帶來的收益,是整個sta的1的數量,盡量取大的,最小的那個.
為什麼要看sta的1的數量呢?(而不是s),如果看了s,辣答案肯定偏大;如果看sta,這一次可能不是最大的,但總有一種方案能湊到可能最大的,
仔細體會一下…
#include
using
namespace std;
typedef
long
long ll;
int n,m;
int a[20]
;int dp[
1<<15]
;bool vis[
1<<15]
;int
main()
sort
(a+1
,a+1
+n);
for(
int i=
1;i<=m;
++i)
vis[res]=1
;}for(
int sta =
1;sta<(1
<;++sta)
else}}
cout<< sum - dp[(1
<]
}
待補
其實是個水題…然後我wa了半天
注意到當前的操作只影響左邊,辣從右往左做,一定就是最新的結果辣
先統計操作的次數,然後做相應操作即可. 樹狀陣列/線段樹均可.
#include
using
namespace std;
typedef
long
long ll;
const
int mod =
1e9+7;
const
int maxn =
1e5+10;
ll node[maxn+10]
;//存差分
int n,m;
ll add
(ll x, ll y)
struct nodeno[maxn+10]
;inline
intlowbit
(int x)
void
add(
int x, ll value,
int up)
ll get
(int x)
intmain()
for(
int i=m;i>=1;
--i)
}memset
(node,0,
sizeof
(node));
for(
int i=
1;i<=m;
++i)
}for
(int i=
1;i++i)
cout<<
get(n)
;return0;
}
待補
待補 牛客練習賽9
時間限制 c c 1秒,其他語言2秒 空間限制 c c 32768k,其他語言65536k 64bit io format lld 珂朵莉想每天都給威廉送禮物,於是她準備了n個自己的本子 她想送最多的天數,使得每天至少送乙個本子,但是相鄰兩天送的本子個數不能相同 珂朵莉最多送幾天禮物呢 第一行乙個整...
牛客練習賽15
時間限制 c c 2秒,其他語言4秒 空間限制 c c 262144k,其他語言524288k 64bit io format lld 第一次期中考終於結束啦!沃老師是個語文老師,他在評學生的作文成績時,給每位學生的分數都是乙個小於10的非負小數。amy 8.99999999999999999999...
牛客練習賽5
給你n個正整數,n 5,每個正整數大小不超過1000,最初su m 0 sum 0 每次可將su m sum 按順序加上陣列中的數,加完之後可以對sum的數字進行全排列,求最終能達到的最大值。由於n只有5,所以按照題意模擬dfs實現就可以了,注意最後一組也可以按數字進行全排列。d題 include ...