10月19日

10月19日
今天的题除了第二题比较难,其他的都比较简单。第三题在考试的时候想到了动态规划,然而并没有写出来,所以写了一个0分的暴力。。
第二题没有写出来,最后只有T1得了100分。
———————————————————————————————————————————————————————————————————
对于T1:
一道十分简单的模拟+进制转换。
对于T2:
一开始想到的是并查集,然后发现并没有什么卵用,又想可不可以写网络流,发现也没有用。最后连暴力都不知道怎么写,醉了。。
好吧,正解是——搜索。
最简单的搜索办法:开始把P[0] ~ P[n-1]都未标号,每次枚举一个未标号的点和一个已标号的点,建立一条边。
同时考虑树的深度不能超过D,以及每个点的转发限制就可以搜出结果。然而时间爆炸。。。QAQ
加优化~~优化~~优化,重要的事情说三遍。。。把已经加入数的点标上序号,依照序号从小到大的顺序顺序枚举该节点的儿子节点。
在递归的每一层,枚举了一个节点指定节点的儿子节点以后,深入至下一层是要么枚举下一个该指定节点的儿子节点,要么推移至序号加1
的指定节点寻找儿子节点。至此效率已优化至O(n/2)^2n。
对于T3:
又是动态规划的题目,考完后分析发现还是蛮简单的。由于实验基地的形状必须是“凹”形,所以我们考虑定义三个状态,用dp[i][0]、
dp[i][1]、dp[i][2]分别表示到第i列,左边部分、中间凹下去的部分、右部分的最优解,那么状态转移方程可以定义为:
dp[i][0] = max(dp[i-1][0],judge) + a[1][i] + a[2][i];     <---------左边部分
dp[i][1] = max(dp[i-1][1],dp[i-1][0]) + a[2][i];v         <---------中间凹下去的部分
dp[i][2] = max(dp[i-1][2],dp[i-1][1]) + a[1][i] + a[2][i];<---------右部分
于是本题得以完美解决。
———————————————————————————————————————————————————————————————————
下面附上代码:

T1:

using namespace std;
int x,i,n,a,j,sum,tot;
string strings;
int last[64010],ans[64010];
int getint()
{
	char c = getchar();
	int f = 1,k = 0;
	if(c == '-') f = -1;
	for(; c < '0' || c > '9'; c = getchar());
	for(; c >= '0' && c <= '9'; c = getchar())
	 	k = k * 10 + c - '0';
	return k * f;
}

string change(int a)
{
	char s[9] = {'0','0','0','0','0','0','0','0'};
	string ss;
	int tot = -1;
	while(a != 0)
	{
		x = a % 2;
		s[++tot] = x + '0';
		a /= 2;  
	}
	for(int j = 7; j >= 0; j--)
	{
		ss += s[j]; 
	}
	return ss;
}

int main()
{
	string s1;
	n = getint();
	for(i = 1; i <= n / 8; i++)
	{
		a = getint();
		s1 = change(a);
		for(j = 0; j <= s1.size()-1; j++)
			strings += s1[j];
	}
	//cout << strings << endl;
	tot = 0;
	sum = 1;
	last[++tot] = strings[0] - '0';
	for(i = 1; i <= strings.size()-1; i++)
	{
		if(last[tot] != strings[i] - '0')
		{
			if(strings[i-1] - '0' == 1)
				ans[tot] = 128 + sum;
			else
				ans[tot] = sum;
			sum = 1;
			last[++tot] = strings[i] - '0';
		}
		else
		{
			sum++;
		}
	}
	if(strings[i-1] - '0' == 1)
		ans[tot] = 128 + sum;
	else
		ans[tot] = sum;
	for(i = 1; i <= tot - 1; i++)
	{
		cout << ans[i] << " ";
	}
	cout << ans[tot] << endl;
	return 0;
}

T2:

还没调出来。。

T3:

using namespace std;
long long dp[500010][3];
int a[3][500010],i,j,n;
int getint()
{
	char c = getchar();
	int f = 1,k = 0;
	if(c == '-') f = -1;
	for(; c < '0' || c > '9'; c = getchar());
	for(; c >= '0' && c <= '9'; c = getchar())
		k = k * 10 + c - '0';
	return k * f;
}

int main()
{
	n = getint();
	for(i = 1; i <= 2; i++)
	{
		for(j = 1; j <= n; j++)
		{
			a[i][j] = getint();
		}
	}
	long long judge = 0;
	for(i = 1; i <= n; i++)
	{
		dp[i][0] = max(dp[i-1][0],judge) + a[1][i] + a[2][i];
		if(i >= 2)dp[i][1] = max(dp[i-1][1],dp[i-1][0]) + a[2][i];//注意这里要写i>=2,下面要写i>=3。因为左边必 
		if(i >= 3)dp[i][2] = max(dp[i-1][2],dp[i-1][1]) + a[1][i] + a[2][i];//须先选,再选中间和右边
	}
	long long maxx = -10000000000;
	for(i = 1; i <= n; i++)
		maxx = max(maxx,dp[i][2]);
	cout << maxx << endl;
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值