日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ACM2023SWJTU寒假选拔赛2不完全题解

發布時間:2024/3/13 编程问答 60 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ACM2023SWJTU寒假选拔赛2不完全题解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • 2022.01.15.更新D | L:數學找規律 | dfs(tle)->貪心模擬
  • 2022.01.14.更新L題:統計連通子圖數模型,三解:dsu,bfs,dfs

文章目錄

  • B - 這是一道方塊題 [CodeForces 272C](https://vjudge.net/problem/CodeForces-272C/origin)
  • [E - 這是一道果果題](https://vjudge.net/problem/CodeForces-743B)[CodeForces - 743B ](https://vjudge.net/problem/CodeForces-743B/origin)
  • [G - 這是一道樹林題](https://vjudge.net/problem/POJ-3090)[POJ - 3090](https://vjudge.net/problem/POJ-3090/origin)
  • [J - 這是一道貓咪題](https://vjudge.net/problem/CodeForces-1070D)[CodeForces - 1070D ](https://vjudge.net/problem/CodeForces-1070D/origin)
  • [L - 這是一道玩具題](https://vjudge.net/problem/CodeForces-1209D) [CodeForces - 1209D](https://vjudge.net/problem/CodeForces-1209D/origin)
  • [D - 這是一道算數題](https://vjudge.net/problem/Gym-104090D)[Gym - 104090D ](https://vjudge.net/problem/Gym-104090D/origin)
  • [K - 這是一道奶茶題](https://vjudge.net/problem/CodeForces-863B) [CodeForces - 863B ](https://vjudge.net/problem/CodeForces-863B/origin)

B - 這是一道方塊題 CodeForces 272C

線段樹模版題
Description

一天,公孫晚霽正在玩這款新型的俄羅斯方塊游戲,游戲中一共有$ n $列空間,她將方塊排列成了從左到右下方填滿,依次增高的階梯形狀 第一列的高度為 a 1 a_1 a1?,第二列的高度為 a 2 a_2 a2?,…,第 n列的高度為 $ a_n (1≤a1≤a2≤…≤an)。$

這時,公孫英朗來給公孫晚霽搗亂了,他搶過了游戲手柄,將接下來的 mm 塊方塊都移動到最左側,依次下落,第 i塊方塊的寬為 w i w_i wi?,高為 h i h_i hi?。請幫公孫晚霽計算一下,每塊方塊下落后,方塊下邊緣距離游戲場景底部的距離。

如圖

Input

  • 列數n
  • 每列高度 a 1 , a 1 , . . . , a n {a1,a1,...,an} a1,a1,...,an
  • 新方塊數m
  • 每個方塊尺寸 w , h w,h w,h

Output

一共輸出 mm 行,每行一個整數,表示方塊落下后,下邊緣距離游戲場景底部的距離。

Solution

線段樹板子,每個方塊下落時,落在區間最值 m a x n ( 1 : w ) maxn(1:w) maxn(1:w)位置,這個區間被賦新值 a ( 1 : w ) = m a x n + h a(1:w)=maxn+h a(1:w)=maxn+h

Code

#include<bits/stdc++.h> using namespace std; using ll=long long;const int N=1e5+5;ll a[N]; ll d[N<<2]={0}; ll tag[N<<2]={0};inline int left(int i) { return i<<1; } inline int right(int i) { return i<<1|1; } inline int fa(int i) { return i>>1; }inline void push_up(int p) { //線段樹維護區間最值d[p] = max(d[left(p)] , d[right(p)] ); } inline void push_down(int l,int r,int p) {if (!tag[p]) return;int mid = (l + r) >> 1;tag[left(p)] = tag[p];tag[right(p)] = tag[p];d[left(p)] = tag[p];d[right(p)] = tag[p];tag[p] = 0; }void build(int l,int r,int p) {if(l==r) {d[p]=a[l];return; }int mid=(l+r)>>1;build(l,mid,left(p));build(mid+1,r,right(p));push_up(p); } ll query(int lo,int hi,int l,int r,int p) {ll res=0;if(lo<=l && r<=hi) return d[p];int mid=(l+r)>>1;push_down(l,r,p);if(lo<=mid) res=max(res,query(lo,hi,l,mid,left(p)));if(hi>mid) res=max(res,query(lo,hi,mid+1,r,right(p)));return res; } void update(int lo,int hi,int l,int r,int p,ll elm) {//區間修改操作位區間賦值if(lo<=l && r<=hi){d[p]=elm;tag[p]=elm;return;}push_down(l,r,p);int mid = (l + r) >> 1;if (lo <= mid) update(lo, hi, l , mid, left(p),elm);if (hi > mid ) update(lo, hi, mid+1, r , right(p),elm);push_up(p); } int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int n;cin>>n;for(int i=1;i<=n;i++){cin>>a[i];}build(1,n,1); // for(int i=1,lvl=0;i<=4*n;lvl++) {for(int j=1;j<=1<<lvl;j++) cout<<d[i++]<<" "; cout<<'\n';}int m;cin>>m;while(m--){int w,h;cin>>w>>h;ll maxn=query(1,w,1,n,1);cout<<maxn<<'\n';update(1,w,1,n,1,maxn+h);}return 0;}

E - 這是一道果果題CodeForces - 743B

找規律
Description

公孫英朗給公孫晚霽買了很多果果,公孫晚霽很喜歡,但是為了她的減肥計劃,她一天不能吃太多果果。
公孫晚霽的減肥計劃由n步生成,生成過程如下:

  • 第一步規定第1天只能吃一個果果;
  • 隨后每一步,將之前確定的所有計劃復制附加在末尾,并在中間插入未使用過的最小正整數。

根據這個過程,當n=1時,該計劃進行一天,這天可以吃的果果數量為1。
當n=2時,該計劃進行三天,這些天可以吃的果果數量為[1,2,1]。
當n=3時,該計劃進行七天,這些天可以吃的果果數量為[1,2,1,3,1,2,1].請你幫公孫晚霽計算一下,依照該計劃,第k天她能吃多少果果。

Input

1 ≤ n ≤ 50 , 1 ≤ k ≤ 2 50 ? 1 1\le n \le 50,1\le k \le 2^{50} -1 1n50,1k250?1

Solution

這個序列為, { 1 1 , 2 2 , 1 3 , 3 4 , 1 5 , 2 6 , 1 7 , 4 8 , 1 9 , 2 10 , 1 11 , 3 12 , 1 13 , 2 14 , 1 15 , 5 16 , 1 , 2 , 1 , 3 , 1 , 2 , 1 , 4 , 1 , 2 , 1 , 3 , 1 , 2 , 1 , . . . } \{1_1,2_2,1_3,3_4,1_5,2_6,1_7,4_8,1_9,2_{10},1_{11},3_{12},1_{13},2_{14},1_{15},5_{16},1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,...\} {11?,22?,13?,34?,15?,26?,17?,48?,19?,210?,111?,312?,113?,214?,115?,516?,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,...}

可以觀察出一些性質

  • 2 i 2^i 2i個元素,其值為 i + 1 i+1 i+1
  • K K K個元素,由**“復制”**的特性,其值等于第 K ? ( 1 < < l g ( K ) ) K-(1<<lg(K)) K?(1<<lg(K))個元素

tle遞推式子

ll query(ll k) { ll bin=0;while( ( 1<<bin ) <= k) bin++; bin--;if(k==1<<bin) return bin+1;else return query(k-(1<<bin));

這個bin是難求而重復的,tle了,如果通過map記憶化遞歸推lg,mle了

繼續觀察這個序列 1 , 2 , 1 , 3 , 1 , 2 , 1 , 4 , 1 , 2 , 1 , 3 , 1 , 2 , 1 {1,2,1,3,1,2,1,4,1,2,1,3,1,2,1} 1,2,1,3,1,2,1,4,1,2,1,3,1,2,1

1: 1 3 5 7 9... beg=2^0,del=2^1 2: 2 6 10 ,... beg=2^1,del=2^2 3: 4 12 20 ,... beg=2^2,del=2^3 4: 8 ,... beg=2^3,del=2^4

根據這個來求就好了:減去beg,判是否整除del

Code

ll querr(ll n,ll k) {for(ll i=1;i<=n+1;i++){ll tmp=k-(1ll*1<<(i-1));if(tmp%(1ll*1<<(i))==0) {return i;}} }

G - 這是一道樹林題POJ - 3090

歐拉篩模版題

學校里的小樹林種成了一個 ( n + 1 ) ? ( n + 1 ) (n+1) * (n+1) (n+1)?(n+1) 大小的密密麻麻的正方形矩陣,公孫英朗和公孫晚霽在樹林里捉迷藏。
公孫英朗面朝樹干,公孫晚霽躲了起來。3…2…1… 隨后公孫英朗轉頭,開始捉公孫晚霽啦~

公孫英朗從 (0, 0) 的位置轉頭,公孫晚霽就藏在了這些樹后邊,因為樹之間有遮擋關系,公孫英朗只能看見一部分樹,請幫公孫晚霽計算一下,公孫英朗能看見多少樹。

小樹林中每一顆樹都看做平面直角坐標系下的一個個點,從 (0, 0) 到 (n, n)都種滿了樹。當 n=5時,小樹林的樣子如下圖所示:

當某點與 (0, 0的連線上有其它點時,該點會被連線上的點遮擋,公孫英朗就看不見這棵樹了,如 (4, 2)這棵樹會被 (2, 1)這棵樹擋住,公孫英朗看不見位于 (4, 2) 的這課樹。

Input

樣例數T 1 ≤ T ≤ 1 e 3 1 \le T \le 1e3 1T1e3

矩陣規模n 1 ≤ n ≤ 1 e 3 1 \le n \le 1e3 1n1e3

Output

看見的樹木cnt

Solution

對于起點為原點的射線,可由斜率唯一確定。

用map記錄每一對 ( i , j ) (i,j) (i,j)的斜率,打表也能過,不優化是 O ( T n n l o g n ) O(Tnnlogn) O(Tnnlogn),T了

正解是歐拉函數板子。

歐 拉 函 數 : 小 于 等 于 n 的 與 n 互 質 的 正 整 數 的 個 數 歐拉函數:小于等于n的與n互質的正整數的個數 nn
φ ( n ) = { n ? 1 , n 為 質 數 j ? φ [ i ] , i j = n , i % j = = 0 ( j ? 1 ) ? φ [ i ] , i j = n \varphi(n)= \begin{cases} n-1&,n為質數\\ j * \varphi[i]&,ij=n,i\%j==0\\ (j-1) *\varphi[i]&,ij=n\\ \end{cases} φ(n)=??????n?1j?φ[i](j?1)?φ[i]?,n,ij=n,i%j==0,ij=n?

矩陣左上角與右下角是對稱的,考慮一半就好.

考查右下角三角形內任意數對 ( x , y ) ( 1 ≤ x ≤ y ) (x,y)(1\le x \le y) (x,y)(1xy)

其唯一確定斜率 k = y x k=\frac{y}{x} k=xy?,當 g c d ( x , y ) ! = 1 gcd(x,y)!=1 gcd(x,y)!=1時,這個斜率可由其左下角某個數對表示(成比例)

反之,當 g c d ( x , y ) = = 1 gcd(x,y)==1 gcd(x,y)==1時,即k不可再約,這個元素不重復

暨,給定 x = C x=C x=C,任取 1 ≤ y ≤ n 1\le y\le n 1yn,不重復的斜率 k = y x k=\frac{y}{x} k=xy?滿足xy互質,這正是歐拉函數的定義

a n s = 3 + 2 ? ∑ 2 n p h i [ i ] ans=3+2*\sum_2^n phi[i] ans=3+2?2n?phi[i]

Code

void phis() {phi[1]=1;for(int i=2;i<=N;i++){if(!vis[i]){prime[cnt++]=i;phi[i]=i-1;}for(int j=0;j<cnt && i*prime[j]<=N;j++){vis[prime[j]*i]=1;if(i%prime[j]==0){phi[i*prime[j]]=prime[j] * phi[i];break;}else phi[i*prime[j]]=(prime[j] -1 ) *phi[i]; }} } void solve(int n) {ll ans=0;for(int i=2;i<=n;i++) ans+=phi[i];ans=ans*2+3;cout<<ans<<"\n"; }int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);phis();int T;cin>>T;for(int i=1;i<=T;i++){int n;cin>>n;cout<<i<<" "<<n<<" ";solve(n);}return 0;}

J - 這是一道貓咪題CodeForces - 1070D

小模擬
Description

公孫晚霽領養了一只學校里的流浪貓咪,并將給貓咪剪指甲這個工作交給了公孫英朗,讓貓咪做公孫英朗的貓主子。

假設貓咪指甲的正常長度為一確定值,且當貓咪的指甲長度比正常長度長出長度為 k k k 時,可能會傷到別人,因此當貓咪的指甲達到$ 正常長度 +k$ 時就必須進行一次修剪貓咪的指甲長得很快,一個月之內可能進行多次修剪。為了保護貓咪,指甲不能被剪到正常長度以下,且晚霽認為貓咪當月長出的指甲必須在當月或下個月被剪掉。

已知貓咪當前的指甲長度為正常長度,接下來的 n n n個月中的第 i i i個月,貓咪指甲會增長的長度為$ a_i 。 ? ? 公 孫 英 朗 想 要 讓 個 月 結 。**公孫英朗想要讓個月結 ?? n $束后,貓咪的指甲仍然為正常長度**。請計算公孫英朗最少需要修剪貓咪指甲的次數cnt。

正常長度=0

Input

第一行包含兩個整數 n和k ( 1 ≤ n ≤ 2 ? 1 0 5 , 1 ≤ k ≤ 1 0 9 (1 \le n \le 2\cdot10^5, 1 \le k \le 10^9 (1n2?105,1k109,表示月份的數量和指甲可以超出正常長度的最長長度。

第二行包含 nn 個整數 a_i ( 0 ≤ a i ≤ 1 0 9 ) (0 \le a_i \le 10^9) (0ai?109),表示第 i個月貓咪指甲的增長長度

:當貓爪長度逾k后,需立即修剪。

Solution

模擬

Code

#include<bits/stdc++.h> using namespace std; using ll=long long;const int N=1e5+5;int vis[N]={0}; int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int n,m;cin>>n>>m;int cnt=0; for(int i=1;i<=m;i++){int x,y;cin>>x>>y;if(vis[x] && vis[y]){cout<<i<<' ';cnt++;}vis[x]=1;vis[y]=1;}cout<<cnt;return 0;}

L - 這是一道玩具題 CodeForces - 1209D

圖論連通分量建模
Description

公孫晚霽和公孫英朗打算去孤兒院做志愿活動。第一次去之前,公孫晚霽準備了 nn 種玩具各一個,送給 mm 小朋友們玩。在這 nn 種玩具中,每個小朋友都有2種喜歡的玩具。分玩具的步驟為:

  • 首先,小朋友將按照公孫英朗的要求進行排隊。
  • 然后小朋友按照排隊順序逐一獲取玩具。
  • 每個小朋友會拿走他/她喜歡的所有玩具。
  • 沒有拿到玩具的小朋友將會很傷心,拿到玩具的小朋友將會很開心。

已知每個小朋友喜歡的玩具的種類。請幫公孫英朗計算傷心的小朋友最少有幾個?

Input

玩具個數n,小朋友個數m

每個小朋友喜歡的玩具 x i , y i xi,yi xi,yi

Output

傷心的小朋友個數cnt

Solution

圖論建模,將玩具建模為點,將小朋友建模為兩點之間的邊。對于一張有n個點的連通圖,可以證明地是最多同時滿足n-1個小朋友,即,策略是,按拓撲序加入n-1條邊,所形成的最小生成樹。此后所有點被鏈接,新邊無法加入(sad people)

而題面所述的圖可能是不連通的,求其連通分量數目即可。有bfs,dfs,dsu三種解法

A N S = M ? ( n ? c o u n t ( ) ) ANS=M-(n-count()) ANS=M?(n?count())

Code

  • dsu 62 ms,3900 KB

邊集數組存圖,用并查集來維護連通分量:將連通的點放在同一個集合(共祖先)里,統計dsu映射中祖先的個數即可知集合的個數

#include<bits/stdc++.h> using namespace std; using ll=long long;// 連通分量問題:將玩具建模為點,將child建模為兩點之間的邊:每入一條邊,其兩端的點被vis。 //在一張n個點(玩具)m條邊(child)的連通圖中,通過適當的(拓撲序)讀邊,可以滿足N-1個child。(生成樹) //考查本題所建模的圖,可以是不連通而有若干連通分量的,用并查集來維護連通分量數。 const int N=1e5+5,M=2*N; struct Edge{int from,to; }edge[M]; int cnt_e=0; void add(int u,int v) {edge[++cnt_e].from=u;edge[cnt_e].to=v; } int n,m; //dsu int dsu[N]={0}; int find(int x) { return dsu[x]==x?x:dsu[x]=find(dsu[x]);} void unite(int lhs,int rhs) {dsu[find(rhs)]=find(lhs); }int vis[N]; int count() {int cnt=0;for(int i=1;i<=n;i++){if(!vis[find(i)]){vis[find(i)]=1;cnt++;}}return cnt; } int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>n>>m;for(int i=1;i<=n;i++) dsu[i]=i;for(int i=1;i<=m;i++){int u,v;cin>>u>>v;add(u,v);add(v,u);unite(u,v);}cout<<max(0,m-(n-count()));return 0;}

bfs 78 ms 2600 KB

鏈式前向星存圖,每次bfs為訪問過的邊打上

#include<bits/stdc++.h> using namespace std; using ll=long long;// 連通分量問題:將玩具建模為點,將child建模為兩點之間的邊:每入一條邊,其兩端的點被vis。 //在一張n個點(玩具)m條邊(child)的連通圖中,通過適當的(拓撲序)讀邊,可以滿足N-1個child。(生成樹) //考查本題所建模的圖,可以是不連通而有若干連通分量的,用并查集來維護連通分量數。 const int N=1e5+5,M=2*N; struct Edge{int to, nxt; }edge[M]; int cnt_e=0; int head[N]={0}; void add(int u,int v) {edge[++cnt_e].to=v;edge[cnt_e].nxt=head[u];head[u]=cnt_e; } int n,m; bool vis[N]={0}; int cnt=0; void bfs(int beg) {if(!vis[beg]) cnt++;queue<int> que;que.push(beg);while(!que.empty()){int u=que.front();que.pop();if(!vis[u]){vis[u]=1;for(int j=head[u];j;j=edge[j].nxt){int to=edge[j].to;if(!vis[to]){que.push(to);}}}} } int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>n>>m;for(int i=1;i<=m;i++){int u,v;cin>>u>>v;add(u,v);add(v,u);}for(int i=1;i<=n;i++) bfs(i);cout<<max(0,m-(n-cnt));return 0;}

dfs 同上 鏈式前向星存圖 62 ms 5200 KB

void dfs(int u) {if(vis[u]) return;vis[u]=1;for(int j=head[u];j;j=edge[j].nxt){int to=edge[j].to;if(!vis[to]) dfs(to);} } for(int i=1;i<=n;i++) {if(!vis[i]){cnt++;dfs(i);} }

效率比較

D - 這是一道算數題Gym - 104090D

awesome找規律

Description

公孫英朗的算數技能太差了,公孫晚霽決定給公孫英朗進行算數訓練。
公孫晚霽準備了nn個整數,公孫英朗需要按順序完成以下操作:

  • 將第i個數減去一半,并將減掉的部分加到第i+1個數上;
  • 將第 n 個數減去一半,并將減掉的部分加到第1個數上;

為了讓公孫英朗表達對自己的愛意,公孫晚霽決定讓他執行以上訓練過程 520131 4 33441573 5201314^{33441573} 520131433441573輪。請幫公孫英朗計算出執行后的最終結果。

Solution

**打表看看每輪結果,最終結果會固定。**而while(1)等其固定會tle

再找找規律:
K = s u m / ( n + 1 ) a 1 = 2 K , a i = K K=sum/(n+1)\\ a1=2K,ai=K K=sum/(n+1)a1=2K,ai=K

1. 在減數和搬運的過程中,sum守恒,數列的總和從未改變

2. 基于若干次操作后,數列趨于穩定的事實:

3. 對于“將第i個數的一半搬運給第i+1個數”這個回圈的操作,2:1:1:1:1...這個比例滿足穩定的需求。

將sum分為n+1份,a1占兩份,其余占一份

Code

#include<bits/stdc++.h> using namespace std; using ll=long long;const int N=1e5+5; int n; double a[N]; int main() { // ios::sync_with_stdio(false); // cin.tie(0);cout.tie(0);double sum=0;cin>>n;for(int i=1;i<=n;i++){cin>>a[i];sum+=a[i];}double k=sum/(n+1);printf("%f ",2*k);for(int i=2;i<=n;i++) printf("%f ",k); // puts(""); // double last=-1; // while(1) // { // // for(int i=1;i<n;i++) // { // a[i]/=2; // a[i+1]+=a[i]; // } // a[n]/=2; // a[1]+=a[n]; // if(last==a[1]) // { // for(int i=1;i<=n;i++)printf("%f ",a[i]); // return 0; // } // last=a[1]; // // }return 0;}

K - 這是一道奶茶題 CodeForces - 863B

Description

公孫英朗打算請大家喝奶茶,于是他和公孫晚霽兩人到奶茶店,下單了 2 n 2n 2n 杯不同的飲品。

由于購買了偶數杯,公孫晚霽本打算全部使用兩杯裝一起的方式打包帶到 T 6023 T6023 T6023。但不幸的是,奶茶店僅剩了 n ? 1 n-1 n?1 個兩杯裝袋子和若干一杯裝袋子。于是公孫晚霽不得己決定使用全部的兩杯裝包裝,再使用2個一杯裝包裝進行打包。

當使用兩杯裝包裝時,公孫晚霽發現因為每杯重量不同,這些包裝會產生不平衡值,若這兩杯的重量分別為 u u u v v v,則不平衡值為$ abs(u-v)$。一杯裝包裝不產生不平衡值。

拎著奶茶的公孫英朗想讓不平衡值的和盡可能小,請你求出該最小值。

Input

n , 1 ≤ n ≤ 50 n,1\le n\le 50 n,1n50

奶茶重量 { a 0 , a 1 , . . . , a 2 n } \{a0,a1,...,a2n\} {a0,a1,...,a2n}

Output

ans

人話

一個序列,選擇兩個數去掉,其他的自由組合,使總差和最小

Solution

貪心地認為,同一個袋子里的兩杯奶茶重量應該接近

即,若先對數組排序,然后分組,同組兩杯奶茶是相鄰的。

即,從序列 1 , 2 , 3 , 4 , . . , 2 n {1,2,3,4,..,2n} 1,2,3,4,..,2n中有 2 n ? 1 2n-1 2n?1對相鄰元素,選取作差最小的前 n ? 1 n-1 n?1對相鄰元素即可

基此可以圖論爆搜:建邊集數組,邊 [ i : ? > i : 1 ] . v a l = a [ i + 1 ] ? a [ i ] [i:->i:1].val=a[i+1]-a[i] [i:?>i:1].val=a[i+1]?a[i]然后按邊權排序,然后dfs搜 n ? 1 n-1 n?1層,每層搜一條弧頭弧尾未vis的邊

Code

DFS θ ( 2 n ) n ? 1 \theta(2n)^{n-1} θ(2n)n?1,TLE

#include<bits/stdc++.h> using namespace std; using ll=long long;const int N=55; int n; int a[2*N];struct Edge{int from,to,val; }edge[2*N]; int cnt_e=0; void add(int u,int v,int val) {edge[cnt_e].from=u;edge[cnt_e].to=v;edge[cnt_e++].val=val; } bool cmp(const Edge& lhs,const Edge& rhs) {return lhs.val<rhs.val;}bool vis[N]={0};int ans=0x7f7f7f7f; vector<Edge> vec; void dfs(int lvl,int sum) {if(lvl>n-1){cout<<sum<<'\n';for(auto it:vec) cout<<it.from<<" "<<it.to<<" "<<it.val<<'\n'; cout<<'\n';ans=min(ans,sum);return;}for(int i=0;i<cnt_e;i++){if(!vis[edge[i].from] && !vis[edge[i].to]){vis[edge[i].from]=1;vis[edge[i].to] =1;vec.push_back(edge[i]);dfs(lvl+1,sum+edge[i].val);vis[edge[i].from]=0;vis[edge[i].to] =0;vec.pop_back();}} } int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>n;for(int i=1;i<=2*n;i++) cin>>a[i];sort(a+1,a+2*n+1);for(int i=1;i<=2*n-1;i++){add(i,i+1,a[i+1]-a[i]);}sort(edge,edge+cnt_e,cmp); dfs(1,0);cout<<ans;return 0;}

枚舉

打表觀察一下選出的組合,還是前邊那句同組兩杯奶茶是相鄰的

而未選用的兩杯奶茶未必相鄰:只需滿足減去這兩個元素后,剩余序列倆倆一組依舊相鄰即可,eg, { _ , 2 , 3 , _ , 5 , 6 , . . } \{\_,2,3,\_,5,6,..\} {_,2,3,_,5,6,..}

能枚舉出所有刪點的情況即可。

刪去兩個點將原序列分為三個區間,需要這三個區間長度均為偶數,才符合依舊相鄰的規則

,eg { 1 , 2 , _ , 4 , 5 , _ , 7 , 8 } \{1,2,\_,4,5,\_,7,8\} {1,2,_,4,5,_,7,8}

刪點策略為:第一個點必為奇數,第二個點與第一個點間隔偶數距離,然后簡單讀相鄰元素差即可。

一點點思維的小模擬。

Code AC

#include<bits/stdc++.h> using namespace std; using ll=long long;int n; const int N=55; int a[2*N]; int b[2*N]; bool vis[2*N]={0}; int ans=0x7f7f7f7f;void solve() {int sum=0;for(int i=1;i<=2*n;){if(vis[i]) i++;if(vis[i]) i++;sum+=a[i+1]-a[i];i+=2;}ans=min(ans,sum); } int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>n;for(int i=1;i<=2*n;i++) cin>>a[i];sort(a+1,a+2*n+1);for(int i=1;i<=2*n;i+=2){vis[i]=1;for(int j=i+1;j<=2*n;j+=2){vis[j]=1;solve();vis[j]=0;}vis[i]=0;}cout<<ans;return 0;}

總結

以上是生活随笔為你收集整理的ACM2023SWJTU寒假选拔赛2不完全题解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。