9.18日志

1.算法板块

今天写了两道洛谷上的dp相关的题目,明天开始学习单调队列优化的dp。

例题1.P3842 [TJOI2007] 线段 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

思考本题的时候我们发现每次准备往下走的时候只可能在本行线段的左端点或者右端点,同理我们也只能从上一行的左端点或者右端点走到当前行的某一端点,这包含了所有的情况,那么我们只需要将状态表示出来并且正确进行状态的转移后在最后一行对于左端点和右端点分别到n点的距离加上dp[l]/dp[r]取最大即可,需要注意的是因为本题n较大若我们创建二维数组表示整张地图的话会爆空间,并且我们又发现每一层的状态只与上一层的有关那么我们可以使用滚动数组优化空间至两维,注意初始化。

#define first x
#define second y
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll , ll> pii;
typedef pair <int , char> pic;
const int N = 2e4 + 10,inf = 0x3f3f3f3f,mod = 80112002;

ll n;
ll l[N],r[N];
ll dp[2][N];		//第i层以j为终点时最少走多少步

int main()
{
	std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);

	cin>>n;

	cin>>l[1]>>r[1];
	ll now = 1;
	dp[now][r[1]] = r[1] - 1;
	dp[now][l[1]] = r[1] - 1 + r[1] - l[1];
	
	for(int i = 2 ; i <= n ; i++)
	{
		cin>>l[i]>>r[i];
		dp[now ^ 1][l[i]] = min(dp[now][l[i - 1]] + 1 + abs(r[i] - l[i - 1]) + r[i] - l[i] , dp[now][r[i - 1]] + 1 + abs(r[i - 1] - r[i]) + r[i] - l[i]);
		dp[now ^ 1][r[i]] = min(dp[now][l[i - 1]] + 1 + abs(l[i - 1] - l[i]) + r[i] - l[i] , dp[now][r[i - 1]] + 1 + abs(r[i - 1] - l[i]) + r[i] - l[i]);
		now ^= 1;
	}	

	cout<<min(dp[now][l[n]] + n - l[n] , dp[now][r[n]] + n - r[n]);
}

例题2.P1064 [NOIP2006 提高组] 金明的预算方案 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

仔细思考本题容易想到这其实是一个分组背包的问题,每一个分组中每一个物品必须包含一个主件,至于附件添加/不添加的所有情况就是一个分组的所有物品,我们只需要为每一个主件开辟一个分组,将所有附件加入到相应的分组,之后用dfs分类出每一个分组里面的所有可能情况,本题数据很阴,会出现附件在主件之前出现的情况,需要特殊处理,将主件附件整理成一个分组背包之后就是正常的背包dp了

#define first x
#define second y
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll , ll> pii;
typedef pair <int , char> pic;
const int N = 100,M = 1e5 + 10,inf = 0x3f3f3f3f,mod = 80112002;

struct node
{
	ll v,q,w;
};

int n,m;
ll dp[M];

void dfs(vector <node> a,vector <node> &b,int now,int v,int q,int w)
{
	if(now == a.size())
	{
		b.push_back({v , q , w});
		return;
	}
	for(int i = now ; i < a.size() ; i++)
	{
		dfs(a , b , i + 1 , v + a[i].v , q + a[i].q , w + a[i].v * a[i].q);
		dfs(a , b , i + 1 , v , q , w);
	}
	
	return;
}

bool cmp(node a,node b)
{
	return a.w < b.w;	
}

int main()
{
	std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);

	cin>>n>>m;

	map <int , int> mp;
	int cnt = 0,idx;
	vector <vector <node> > a(m + 10),b(m + 10);

	for(int i = 1 ; i <= m ; i++)
	{
		int v,p,q;
		cin>>v>>p>>q;
		if(q == 0)
		{
			if(!mp[i])
			{
				mp[i] = ++cnt;
			}
			idx = mp[i];
		}else
		{
			if(!mp[q])
			{
				mp[q] = ++cnt;
			}
			idx = mp[q];
		}
		a[idx].push_back({v , p , q});
	}

	for(int i = 1 ; i <= cnt ; i++)
	{
		sort(a[i].begin() , a[i].end() , cmp);
		dfs(a[i] , b[i] , 1 , a[i][0].v , a[i][0].q , a[i][0].v * a[i][0].q);
	}

	// for(int i = 1 ; i <= idx ; i++)
	// {
	// 	for(int j = 0 ; j < b[i].size() ; j++)
	// 	{
	// 		cout<<b[i][j].v<<" "<<b[i][j].q<<" "<<b[i][j].w<<"---------\n";
	// 	}
	// }

	for(int i = 1 ; i <= cnt ; i++)
	{
		for(int j = n ; j >= 0 ; j--)
		{
			for(int k = 0 ; k < b[i].size() ; k++)
			{
				int v = b[i][k].v,q = b[i][k].q,w = b[i][k].w;
				if(j >= v)
				{
					dp[j] = max(dp[j] , dp[j - v] + w);
				}
			}
		}
	}

	cout<<dp[n];
}

例题3.154. 滑动窗口 - AcWing题库

为明天的单调队列优化dp进行准备,滑动窗口本质是利用双端队列线性求出定长区间内的最值,当队头的坐标与i的距离超过长度k的时候丢弃队头,当队尾元素不如ai的时候直接删除,因为只要ai在队尾元素就不是最优的,而当ai退出队列的时候当前的队尾只会更早退出,因此没有任何意义,并且每个元素只会入队出队一次故是线性。

#define first x
#define second y
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll , ll> pii;
typedef pair <int , char> pic;
const int N = 1e6 + 10,inf = 0x3f3f3f3f,mod = 80112002;

int a[N],q[N];
int n,k;

int main()
{
	std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);

	cin>>n>>k;
	for(int i = 1 ; i <= n ; i++)
	{
		cin>>a[i];
	}		

	int tt = -1,hh = 0;
	for(int i = 1 ; i <= n ; i++)
	{
		while(hh <= tt && q[hh] <= i - k)
		{
			hh++;
		}

		while(hh <= tt && a[i] <= a[q[tt]])
		{
			tt--;
		}

		q[++tt] = i;

		if(i >= k)
		{
			cout<<a[q[hh]]<<" ";	
		}
	}

	cout<<"\n";

	tt = -1,hh = 0;
	for(int i = 1 ; i <= n ; i++)
	{
		while(hh <= tt && q[hh] <= i - k)
		{
			hh++;
		}

		while(hh <= tt && a[i] >= a[q[tt]])
		{
			tt--;
		}

		q[++tt] = i;

		if(i >= k)
		{
			cout<<a[q[hh]]<<" ";
		}
	}
}

2.web板块

今天主要学习了如何使用css去装饰文本,字体和背景
 

h4 {
    text-align: center;
}

.mydiv {
    text-align: center;
    font-size: 50%;
    line-height: 2em;
    letter-spacing: 1.5em;
    text-shadow: 2px 5px 2px grey;
}

.mydiv>p:nth-child(1) {
    text-decoration: green wavy underline;
    font-weight: normal;
}

.mydiv>p:nth-child(2) {
    font-weight: 1000;
}

a {
    text-decoration: none
}

pre {
    font-family: serif monospace
}

.back {
    width: 200px;
    height: 200px;
    background-color: lightblue;
    /*背景颜色*/
    background-image: url(/img/ss.jpg);
    /*背景图片(也可以放颜色)*/
    background-size: 100px 200px;
    /*背景图片的大小*/
    background-repeat: no-repeat;
    /*背景图片的重复方式,也可以不重复*/
    background-position: left 100px;
    /*背景图片位置*/
    background-attachment: fixed;
}

div {
    height: 300px;
    weight: 300px;
}


font-size 表示字体大小
sont-style 定义字体
font-weight 字体粗细
font-family 设置字形
text-align 控制字体居中对齐或者左右对齐
text-height 设置行高
letter-spacing  字间距
text-decoration 定义下划线/波浪线(可调节颜色)
text-shadow 设置阴影
background-color 背景颜色
background-image 背景图片
background-size 图片大小
background-repeat 图片水平/垂直/全部/不重复
background-position  设置图片初始位置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值