2019.08.10 onecode动归专题2

D题:

题意:给定一个具有 N个顶点的凸多边形,将顶点从1 至N 标号,每个顶点的权值都是一个正整数。 将这个凸多边形划分成N−2个互不相交的三角形,试求这些三角形顶点的权值乘积和至少为多少。

思路:区间dp,记f[i][j]为从顶点i到顶点j的答案,则f[i] [j] = f[i] [k] + f[k] [j] + s[i] \times s[j] \times s[k]

#include 
using namespace std;
struct node{
	int a[1100],len;
	node(){
		memset(a,0,sizeof(a));
		len=0;
	}
	void init_maxn(){
		len=1000;a[len]=9;
	}
	node operator = (int b){
		if (b==0) len=1;
		while (b){
			a[++len]=b%10;
			b/=10;
		}
		return *this;
	}
	node operator = (node b){
		memcpy(a,b.a,sizeof(a));
		len=b.len;
		return *this;
	}
	node operator + (node b){
		node c;int x=0;
		c.len=max(len,b.len);
		for(int i=1;i<=c.len;i++){
			c.a[i]=a[i]+b.a[i]+x;
			x=c.a[i]/10;c.a[i]%=10;
		}
		if (x) c.a[++c.len]=x;
		return c; 
	}
	node operator * (node b){
		node c;c.len=len+b.len+10;
		for(int i=1;i<=len;i++){
			register int x=0,j;
			for(j=1;j<=b.len;j++){
				c.a[i+j-1]+=a[i]*b.a[j]+x;
				x=c.a[i+j-1]/10;
				c.a[i+j-1]%=10; 
			}
			if (x) c.a[i+b.len]=x;
		}
		while (c.len>1&&c.a[c.len]==0) c.len--;
		return c;
	}
	bool operator < (node b){
		if (len>b.len) return false;
		if (lenb.a[i]) return false;
		}
		return false;
	}
	void write(){
		for(int i=len;i;i--)
		printf("%d",a[i]);
	}
	void read(){
		string s;cin>>s;len=s.size();
		for(int i=0;i>n;
	for(i=1;i<=n;i++)
	s[i].read();
	use_dp_to_get_answer();
	f[1][n].write();
	return 0; 
}

F题:

题意:一开始LYD可以选择从1~n-1的任何一个区域(记为K)进入,进入后LYD会在K区域发生分离,从而分离为两个小LYD。 分离完成的同时会有一面墙在K和K+1区域之间升起,从而把1~k和k+1~n阻断为两个独立的区间。然后两个小LYD分别进入1~k和k+1~n, 并在各自的区间内任选除了区间末尾区域以外(即1~k-1或k+1~n-1)的任何一个区域再次发生分离,就一共有了4个小小LYD……重复进行以上所叙述的分离, 直到每个小LYD发现自己所在的区间只剩下了一个区域,他们就可以抱起自己梦寐以求的OI金钥匙。 但是LYD不能就这么分成n多个个体存在于世界上,这些小LYD还会再合体,合体的两个小LYD所在的区间中间的墙会消失。 合体会获得一定的价值,计算方法是:(合并后所在区间的左右端区域里金钥匙的价值之和) 乘 (之前分离的时候所在区域的金钥匙价值)。 {例如:LYD曾经在1~3区间中的2号区域分离成为1~2和3两个区间,合并时获得的价值就是(1号金钥匙价值+3号价值)*(2号金钥匙价值)。} LYD请你编程求出最终可以获得的总价值最大是多少。 并按照分离阶段从前到后,区域从左向右的顺序,输出发生分离的区域编号。

思路:区间dp,在计算答案的同时,随便把中间节点给记下来,到时候一遍广搜输出即可

#include 
using namespace std;
int f[330][330],n;
int an[330][330],a[330];
void print_the_answer(){
	printf("%d\n",f[1][n]);
	queue >q;
	q.push(make_pair(1,n));bool flag;
	do{
		pair z=q.front();q.pop();
		int x=z.first,y=z.second;
		if (x==y) continue;
		flag=(x==1)&&(y==n);
		if (flag) printf("%d",an[x][y]);
		else printf(" %d",an[x][y]);
		q.push(make_pair(x,an[x][y]));
		q.push(make_pair(an[x][y]+1,y));
	}while (q.size());
}
//输出答案
void use_dp_to_get_answer(){
	for(int i=1;i<=n;i++)
	f[i][i]=0;
	for(int l=2;l<=n;l++)
	for(int j=l;j<=n;j++){
		int i=j-l+1,p,k;
		for(k=i;kf[i][j]){
				f[i][j]=p;
				an[i][j]=k;
			}
		}
	} 
}
//计算答案且记录中间节点
void read_the_date(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	scanf("%d",&a[i]);
}
//输入
int main(){
	read_the_date();
	use_dp_to_get_answer();
	print_the_answer();
	return 0;
}

 

你可能感兴趣的:(原创)