DP2
找不到什么分类,乱炖就是了。
P10971 Cookies
将 \(g_i\) 从小到大排序,设 \(a_i\) 为 第 \(i\) 个人分到的糖果数,则应有 \(a_{i}\le a_{i+1}\)。
按层考虑,每次我们会选择一段后缀保留,并这段人每人分配一个糖果,因此 \(f_{i,j}\) 表示还剩 \(i\) 个小朋友存活,已经分了 \(j\) 个糖果,枚举下一轮存活的小朋友数 \(k\),有 \(k\le j,i+k\le m\),然后 \(f_{i,j}+k\sum_{l=n-j+1}^{n-k}g_l\to f_{i+k,k}\),因为这一轮去世的小朋友都会比后面的小。
输出方案的话记录一下来源即可。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=33,M=5003;
const ll F=1e18;
int n,m,s[N];
pair<int,int> a[N];
int g[N][M],sum[N];
ll f[N][M],ans=F;
void calc(int x,int y){
if(y==0)return;
for(int i=n;i>=n-x+1;--i)
++sum[a[i].second];
int tx=g[x][y]/M,ty=g[x][y]%M;
calc(tx,ty);
}signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;++i)
cin>>a[i].first,a[i].second=i;
sort(a+1,a+n+1);
for(int i=1;i<=n;++i)
s[i]=s[i-1]+a[i].first;
for(int i=0;i<N;++i)
for(int j=0;j<M;++j)
f[i][j]=F;
f[n][n]=0;
for(int i=n;i<m;++i){
for(int j=n;j>=1;--j){
for(int k=1;k<=j;++k){
if(i+k<=m){
ll tmp=f[j][i]+1ll*k*(s[n-k]-s[n-j]);
if(tmp<f[k][i+k])
f[k][i+k]=tmp,g[k][i+k]=j*M+i;
}
}
}
}
for(int i=1;i<=n;++i)
ans=min(ans,f[i][m]);
cout<<ans<<'\n';
for(int i=1;i<=n;++i){
if(ans!=f[i][m])continue;
calc(i,m);
for(int j=1;j<=n;++j)
cout<<sum[j]<<' ';
cout<<'\n';
break;
}
return 0;
}
P14309 【MX-S8-T2】配对
先考虑偶数。
\(s_u\) 表示 \(u\) 子树内 \(c_i\) 的异或和。若 \(c_u=1\) 则 \((u,fa_u)\) 这条边要算上。然后交换操作就是选择一条 \(c_u=0,c_v=1\) 的路径将这条路径所有点 \(s_i\) 取反。直接 dp,\(f_{u,0/1/2/3}\) 表示 \(u\) 的子树内选了 \(c_v=0\) 的 \(v\to u\) 的链、\(c_v=1\) 的 \(v\to u\) 的链、没有选链、子树内已经将链拼完的最小值。
奇数时相当于还要选一条 \(c_u=1\) 到 \(root\) 的路径将路径 \(s_i\) 取反,再加一维 \(0/1\) 即可表示是否有选即可。
赛事思路凌乱,写的比较暴力。
赛时代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+5;
int n,c[N],s[N],sc;
int head[N],tot;
ll f[N][4][2],g[4][2];
struct edge{int v,w,nxt;}e[N<<1];
void add(int u,int v,int w){
e[++tot]=(edge){v,w,head[u]},head[u]=tot;
e[++tot]=(edge){u,w,head[v]},head[v]=tot;
}ll min(ll x,ll y,ll z,ll w){
return min(min(x,y),min(z,w));
}ll min(ll a,ll b,ll c,ll d,ll e,ll f,ll g,ll h){
return min(min(a,b,c,d),min(e,f,g,h));
}void dfs(int u,int fa){
f[u][2][0]=f[u][s[u]=c[u]][0]=0;
if(c[u])f[u][2][1]=f[u][1][1]=0;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].v,w=e[i].w;
if(v==fa)continue;
dfs(v,u),s[u]^=s[v];
int x=s[v]*w,y=(s[v]^1)*w;
for(int j=0;j<4;++j)
g[j][0]=f[u][j][0],g[j][1]=f[u][j][1];
f[u][2][0]= g[2][0]+f[v][2][0]+x;
f[u][2][1]=min(g[2][0]+f[v][2][1]+y,g[2][1]+f[v][2][0]+x);
f[u][1][0]=min(g[2][0]+f[v][1][0]+y,g[1][0]+f[v][2][0]+x);
f[u][0][0]=min(g[2][0]+f[v][0][0]+y,g[0][0]+f[v][2][0]+x);
f[u][3][0]=min(g[2][0]+f[v][3][0]+x,g[3][0]+f[v][2][0]+x,
g[1][0]+f[v][0][0]+y,g[0][0]+f[v][1][0]+y);
f[u][1][1]=min(g[2][0]+f[v][1][1]+x,g[1][0]+f[v][2][1]+y,
g[1][1]+f[v][2][0]+x,g[2][1]+f[v][1][0]+y);
f[u][0][1]=min(g[0][1]+f[v][2][0]+x,g[2][1]+f[v][0][0]+y,
g[2][0]+f[v][0][1]+x,g[0][0]+f[v][2][1]+y);
f[u][3][1]=min(g[3][0]+f[v][2][1]+y,g[3][1]+f[v][2][0]+x,
g[2][0]+f[v][3][1]+y,g[2][1]+f[v][3][0]+x,
g[1][0]+f[v][0][1]+x,g[1][1]+f[v][0][0]+y,
g[0][0]+f[v][1][1]+x,g[0][1]+f[v][1][0]+y);
}
}signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;++i)
cin>>c[i],sc^=c[i];
for(int i=1,u,v,w;i<n;++i)
cin>>u>>v>>w,add(u,v,w);
for(int i=1;i<=n;++i)
for(int j=0;j<4;++j)
f[i][j][0]=f[i][j][1]=1e18;
dfs(1,0),cout<<f[1][3][sc]<<'\n';
return 0;
}

浙公网安备 33010602011771号