牛客小白月赛 27部分题解
已做BCDEFGJ
B.乐团派对
刚开始想了个贪心,结果不对然后直接转头想dp了。
将能力值排序。
首先我们先分出来一组,能力值最大的分出来一组人数是ana_nan即下标是n−an+1→nn-a_n+1\to nn−an+1→n分出来一组,目前还剩n−ann-a_nn−an个人待分配,然后考虑设计dp
状态表示:fif_ifi考虑前111~iii个人分成的最多组数
状态转移:目前第iii个人可以与前面的人一组,也可以把它丢到最开始分出来的那一组于是不难得出:fi=max(fi−1,fi−ai+1)f_i=max(f_{i-1},f_{i-a_i}+1)fi=max(fi−1,fi−ai+1)
C.光玉小镇
由于坏掉的电线杆数目很小,我们可以用bfs预处理以家和每个电线杆为起点到达其他电线杆距离的最小值。
直接枚举电线杆的顺序查表求最值即可。
全排列枚举(cnt!)(cnt!)(cnt!)会超时需要状态压缩dp枚举(2cnt)(2^{cnt})(2cnt)。
写本题的时候发现unordered_map的键值key不能是pair,举体原因请参考大佬博客加上一些代码就可以使用了。
#include<functional> template <typename T> inline void hash_combine(std::size_t &seed, const T &val) {seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } // auxiliary generic functions to create a hash value using a seed template <typename T> inline void hash_val(std::size_t &seed, const T &val) {hash_combine(seed, val); } template <typename T, typename... Types> inline void hash_val(std::size_t &seed, const T &val, const Types &... args) {hash_combine(seed, val);hash_val(seed, args...); }template <typename... Types> inline std::size_t hash_val(const Types &... args) {std::size_t seed = 0;hash_val(seed, args...);return seed; }struct pair_hash {template <class T1, class T2>std::size_t operator()(const std::pair<T1, T2> &p) const {return hash_val(p.first, p.second);} }; #define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<set> #include<map> #include<cmath> #include<queue> #include<string> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<unordered_map> #include<unordered_set> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int N=210; const ll INF=1e18; int n,m,t; char g[N][N]; unordered_map<pii,int,pair_hash> mp; pii pos[20]; int dist[20][20],a[20]; bool st[N][N]; int d[N][N]; queue<pii> q; int dx[]={1,-1,0,0},dy[]={0,0,1,-1}; ll f[1<<16][17]; void bfs(int now) {q.push(pos[now]);memset(d,0x3f,sizeof d);memset(st,0,sizeof st);d[pos[now].first][pos[now].second]=0;while(q.size()){int x=q.front().first,y=q.front().second;q.pop();if(st[x][y]) continue;st[x][y]=1;if(g[x][y]!='.') dist[now][mp[{x,y}]]=d[x][y];for(int i=0;i<4;i++){int a=x+dx[i],b=y+dy[i];if(a<1||b<1||a>n||b>m||g[a][b]=='#') continue;if(d[a][b]>d[x][y]+1){d[a][b]=d[x][y]+1;q.push({a,b});}}} } int main() {IO;int T=1;//cin>>T;while(T--){cin>>n>>m>>t;for(int i=1;i<=n;i++) cin>>g[i]+1;int cnt=0;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){if(g[i][j]=='S') mp[{i,j}]=0,pos[0]={i,j};else if(g[i][j]=='T') mp[{i,j}]=++cnt,pos[cnt]={i,j};}memset(dist,0x3f,sizeof dist);for(int i=0;i<=cnt;i++) bfs(i);memset(f,0x3f,sizeof f);f[1][0]=0;for(int i=0;i<1<<cnt+1;i++)for(int j=0;j<=cnt;j++)if(i>>j&1) for(int k=0;k<=cnt;k++)if((i-(1<<j))>>k&1) f[i][j]=min(f[i][j],f[i-(1<<j)][k]+dist[k][j]);ll res=INF;for(int i=1;i<=cnt;i++)res=min(res,f[(1<<cnt+1)-1][i]+dist[i][0]);if(res>=0x3f3f3f3f) cout<<-1<<'\n';else{res+=1ll*t*cnt;cout<<res<<'\n';}}return 0;}D.巅峰对决
数据保证,任何时候这n个数字均互不相同。
这个条件非常重要,有了这个条件直接用线段树维护一下区间最大值和最小值即可:如果最大值和最小值的差等于坐标差就满足题意否则不满足。
F.核弹剑仙
正解是bitset+拓扑排序,由于数据范围很小随便搞都能过
我还是补一补正解吧,正好练习一下bitset使用。
剩下的题待做。
要加油哦~
总结
以上是生活随笔为你收集整理的牛客小白月赛 27部分题解的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 你拍一我拍一儿童顺口溜 你拍一我拍一儿童
- 下一篇: ICPC 2019-2020 North