zoukankan      html  css  js  c++  java
  • AGC035D

    AGC035D Add and Remove

    题意

    给出(n)个数,每次删除一个不在两端的数,然后把它的权值加到相邻的两个数上。

    问操作(n-2)次后,所剩的两数之和的最小值

    (nle18)

    题解

    暴力存储每一个数的状态肯定不行。

    考虑计算每一个数被计算了多少次。

    可以发现(1)(n)一定只被计算了1次

    最后一个被消除掉的数应只被计算(2)

    可以发现,如果左端点被计算(x)次,右端点被计算(y)

    那么左右端点之间最后一个被消除的数被计算了(x+y)

    然后就可以开始记忆化搜索了

    注意全部都用(map)存储状态会(TLE),需要把其中一部分用数组存储

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int sz=20;
    int n;
    struct node{
    	int l,r,fl,fr;
    	const bool operator<(const node &p)const{
    		if(l!=p.l) return l<p.l;
    		if(r!=p.r) return r<p.r;
    		if(fl!=p.fl) return fl<p.fl;
    		if(fr!=p.fr) return fr<p.fr;
    	}
    };
    ll a[sz];
    ll g[sz][sz][611][611];
    map<node,ll>dp;
    ll f(int l,int r,int fl,int fr){
    	if(l+1==r) return 0;
    	if(fl<611&&fr<611){
    		if(g[l][r][fl][fr]) return g[l][r][fl][fr];
    	}
    	else if(dp[(node){l,r,fl,fr}]) return dp[(node){l,r,fl,fr}];
    	ll ret=1e18;
    	ll sum=fl+fr;
    	for(int i=l+1;i<=r-1;i++){
    		ret=min(ret,sum*a[i]+f(l,i,fl,sum)+f(i,r,sum,fr));
    	}
    	if(fl<611&&fr<611) return g[l][r][fl][fr]=ret;
    	else return dp[(node){l,r,fl,fr}]=ret;
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    	printf("%lld
    ",a[1]+f(1,n,1,1)+a[n]);
    } 
    
  • 相关阅读:
    Ansible工作架构和原理
    基于WSAAsyncSelect模型的两台计算机之间的通信
    基于Select模型通信程序的编写,编译和执行
    Windows API窗口绘图程序设计
    常用自动化运维工具
    简单的程序发布流程
    TCPIP协议编程:基于UDP协议的局域网聊天工具的研发
    Python 遗传算法实现字符串
    python3 井字棋 GUI
    Docker 容器的跨主机连接
  • 原文地址:https://www.cnblogs.com/river-flows-in-you/p/11726767.html
Copyright © 2011-2022 走看看