NOIP2019打卡-20181208

目录

今日反思

1.动态规划练习题:友好城市

2.动态规划练习题:凸多边形分割

3.动态规划练习题:乘积最大



 今天做了3道题目,花了3小时时间。

今日反思

1.在定义数组大小时需要注意:

这样是错误的:

#include <bits/stdc++.h>
using namespace std;


int a[2e9];


int main(){
    return 0;
}

    

正确方式为:

​
#include <bits/stdc++.h>
using namespace std;

#define MAX 1e9
int a[MAX];


int main(){
    return 0;
}

    

​

或者:

​
#include <bits/stdc++.h>
using namespace std;


int a[2 * 1000000000];


int main(){
    return 0;
}

    

​

 2.在考试时,为了保证某一题可以得到满分,在测试程序正确性的时候一定要测试:

①样例

②2~3组手工小数据(人工可以推算出结果)

③边界数据

④特例数据(针对题目中要求特殊判断的地方而设计的数据)

⑤无解数据(针对题目中要求在无解时输出-1而设计的数据)


3.写程序前一定要先处理好初始值的问题



 

1.动态规划练习题:友好城市

原题链

算法:先将北岸的城市排序,接着再求出南岸的最长不下降子序列的长度即可。

评测结果:TLE(50分)

源代码:

#include <bits/stdc++.h>
using namespace std;
struct node{
	int north;
	int south;
}a[2000040];
bool cmp(node a,node b){
	return a.north < b.north;
}
int ans[2000040];
int main(){
	int n;
	scanf("%d",&n);
	for(int i = 1;i <= n;i++){
		scanf("%d%d",&a[i].north,&a[i].south);
		ans[i] = 1;
	}
	int sum = 0; 
	sort(a + 1,a + n + 1,cmp);
	for(int i = 1;i <= n;i++){
		for(int j = 1;j < i;j++){
			if(a[j].south < a[i].south){
				ans[i] = max(ans[i],ans[j] + 1);
			}
		}
		sum = max(sum,ans[i]);
	}
	printf("%d",sum);
	return 0;
}

 



2.动态规划练习题:凸多边形分割

题面:

给定一个具有N(N<50)个顶点(从1到N编号)的凸多边形,每个顶点的权均已知。问如何把这个凸多边形划分成N-2个互不相交的三角形,使得这些三角形顶点的权的乘积之和最小?

输入文件:第一行 顶点数N 。第二行 N个顶点(从1到N)的权值

输出格式:最小的和的值

输入示例:

5

121 122  123  245  231

输出示例:12214884

算法:运用动态规划算法,枚举三角形的两个顶点并求出最小值即可。

评测结果:无(没有提交的地方,但样例已过)

源代码:

#include <bits/stdc++.h>
using namespace std;
int a[110],f[110][110];
int main(){
	int n;
	cin>>n;
	memset(f,0x3f3f,sizeof(f));
	for(int i = 1;i <= n;i++)
		cin>>a[i];
	int j;
	for(int i = 1;i <= n;i++){
		f[i][i + 1] = 0;
	}
	for(int dis = 2;dis <= n;dis++){
		for(int i =  1;i <= n - dis;i++){
			j = dis + i;
			for(int k = i - 1;k < j;k++){
				f[i][j] = min(f[i][j],f[i][k] + f[k][j] + a[i] * a[k] * a[j]);
			}
		}
	}
	cout<<f[1][n];
	return 0;
}


3.动态规划练习题:乘积最大

原题链

算法:区间DP,枚举每一个区间,再逐渐扩散到整个问题即可。

评测情况:20分(未加高精度算法)

源代码:

#include <bits/stdc++.h>
using namespace std;
int d[50][50];
int f[50][50];
int n,K;
string s;
void init() {
    for(int i = 1; i <= n; i++) {
        for(int j = i; j <= n; j++) {
            for(int m = i; m <= j; m++) {
                d[i][j] =  d[i][j] * 10 + (s[m - 1] - '0');
            }
        }
    }
    for(int i = 1; i <= n; i++) {
        f[i][0] = d[1][i];
    }
    return;
}
int main() {
    cin>>n>>K;
    cin>>s;
    init();
    for(int j = 1; j <= K; j++) {
        for(int i = j + 1; i <= n; i++) {
            for(int p = j; p < i; p++) {
                f[i][j] = max(f[i][j],d[p + 1][i] * f[p][j - 1]);
            }
        }
    }
    cout<<f[n][K];
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值