题目大意
2<=n<=18
暴力
4题中3题不是正解,绝了
暴力n!过不了,优化一下
可以发现一些不相邻的选择的顺序不影响结果,所以每次找一层同时删
这样还是不行,考虑这么一个东西:
假设第t层删了x,第t+1层没有删x+1,第t+2层删x+1不删x+2
那么x+1显然可以在第t+1删掉,不会影响结果
所以维护当前可以删的位置,当x被删掉之后下一层可以删x的前后位置,如果没有这样的就不删
时间感觉是3^n的,发现除去两边的中间部分至少贡献2倍,那么当两边+中间*2>=ans就剪掉
这样就卡过去了
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define ll long long
//#define file
using namespace std;
int p[17],pre[18],nxt[18],n,i,j,k,l,L,st;
ll a[18],ans,sum,sum2,s;
void dg(int t,int b,int B,ll sum,ll sum2)
{
int St,i;
if (sum+sum2>=ans) return;
if (t>n)
{
if (st>n) {ans=sum;return;}
if (B)
dg(st,B,0,sum,sum2);
return;
}
dg(nxt[t],b,B,sum,sum2);
if (b&p[t])
{
B|=p[pre[t]]|p[nxt[t]];
if (t==st && nxt[t]>n) sum2-=a[t]*2;
else
if (t!=st && nxt[t]<=n) sum2+=a[t]*2;
if (t==st) sum+=a[t],St=st,st=nxt[st]; else St=st;
if (nxt[t]>n) sum+=a[t];
a[pre[t]]+=a[t];a[nxt[t]]+=a[t];
nxt[pre[t]]=nxt[t];pre[nxt[t]]=pre[t];
dg(nxt[nxt[t]],b,B,sum,sum2);
nxt[pre[t]]=t;pre[nxt[t]]=t;
a[pre[t]]-=a[t];a[nxt[t]]-=a[t];
st=St;
}
}
int main()
{
#ifdef file
freopen("agc035d.in","r",stdin);
#endif
scanf("%d",&n);scanf("%lld",&sum);n-=2;st=1;
fo(i,1,n) scanf("%lld",&a[i]),sum2+=a[i],p[i]=1<<(i-1),nxt[i]=i+1,pre[i]=i-1;
L=p[n]*2-1;nxt[n+1]=n+1,pre[n+1]=n;sum2*=2;
scanf("%d",&j),sum+=j;
if (n<=0) {printf("%lld
",sum);return 0;}
ans=9223372036854775807ll;
dg(1,L,0,sum,sum2);
printf("%lld
",ans);
fclose(stdin);
fclose(stdout);
return 0;
}
题解
考虑倒推,对于区间[l,r]求最后一个被删掉的数i
形式化一下,求区间[l,r]中删掉i后i往左边贡献x次,往右边贡献y次后的答案
那么a[i]的贡献是a[i]*(x+y),[l,i-1]中往左贡献x次,往右会先走到i再往两边,所以会贡献x+y次,[i+1,r]类似
直接递归计算即可
关于时间复杂度,状态数时n^2*2^n的,因为每对(x,y)会转移到(x,x+y)和(x+y,y)上,而区间个数又是n^2
也许吧我也不会算
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define ll long long
//#define file
using namespace std;
int n,i,j,k,l;
ll a[19];
ll dg(int l,int r,ll x,ll y)
{
ll s,ans=9223372036854775807ll;
int i;
if (l>r) return 0;
fo(i,l,r)
{
s=dg(l,i-1,x,x+y)+dg(i+1,r,x+y,y)+a[i]*(x+y);
ans=min(ans,s);
}
return ans;
}
int main()
{
#ifdef file
freopen("agc035d.in","r",stdin);
#endif
scanf("%d",&n);
fo(i,1,n) scanf("%lld",&a[i]);
printf("%lld
",dg(2,n-1,1,1)+a[1]+a[n]);
fclose(stdin);
fclose(stdout);
return 0;
}