2024/7/23 测试小结

突然听说要考试捏(

没有复习(

T1 是 P1434 [SHOI2002] 滑雪

草这不一眼......等下好像不太会写。一开始脑抽了。暴力建图给每个点跑spfa最长路。

明显地,不是正解。直接跳掉了。

T2 是 P4170 [CQOI2007] 涂色

草这真的是一眼题。10min秒掉。区间dp板子。

\(dp_{i,j}\) 表示区间 \([i,j]\) 的答案。状态转移如下。

\(dp_{i,j}=\begin{cases}\min\{dp_{i,j-1},dp_{i+1,j}\}&(s_i = s_j)\\\min\limits_{k=i}^{j-1} \{dp_{i,k}+dp_{k+1,j}\}&\text{else}\end{cases}\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,dp[505][505];
string str;
signed main(){
	freopen("kokoa.in","r",stdin);
	freopen("kokoa.out","w",stdout);
	cin>>str;
	n=str.size();
	str=" "+str;
	memset(dp,0x3f,sizeof(dp));
	for(int i=1;i<=n;i++) dp[i][i]=1;
	for(int len=2;len<=n;len++){
		for(int i=1;i+len-1<=n;i++){
			int j=i+len-1;
			if(str[i]==str[j]) dp[i][j]=min(dp[i+1][j],dp[i][j-1]);
			else{
				for(int k=i;k<j;k++){
					dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
				}
			}
		}
	}
	cout<<dp[1][n]<<endl;
	return 0;
}

T3 是 CF161D Distance in Tree。一眼淀粉质,可惜不会写。

首先想到计数dp。推了个扇贝式子。于是放弃。过了5min,发现这不一眼简单树形dp吗?

\(dp_{i,j}\) 表示以 \(i\) 为根的子树内从 \(i\) 开始长度为 \(j\) 的路径数量。

设当前节点为 \(x\),一个邻接点为 \(y\),贡献即为 \(\sum\limits_{i=0}^{k-1} dp_{y,i} dp_{x,k-i-1}\)

对于一个 \(1 \le j \le k\),每次转移将 \(dp_{x,j}\) 加上 \(dp_{y,j-1}\) 即可。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,k;
struct node{
	int to,nxt;
}w[114514];
int h[114514],cnt=0;
void Link(int x,int y){
	++cnt;
	w[cnt].to=y;
	w[cnt].nxt=h[x];
	h[x]=cnt;
	return ;
}
int read() {
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
	return x*f;
}
int ans=0,dp[114514][505];
void dfs(int x,int fa){
	dp[x][0]=1;
	for(int i=h[x];i!=0;i=w[i].nxt){
		int y=w[i].to;
		if(y==fa) continue;
		dfs(y,x);
		for(int j=0;j<k;j++) ans+=dp[y][j]*dp[x][k-j-1];
		for(int j=1;j<=k;j++) dp[x][j]+=dp[y][j-1];
	}
	return ;
}
signed main(){
	freopen("rize.in","r",stdin);
	freopen("rize.out","w",stdout);
	n=read(); k=read();
	for(int i=1;i<n;i++){
		int u,v;
		u=read(); v=read();
		Link(u,v);
		Link(v,u);
	}
	dfs(1,0);
	cout<<ans<<endl;
	return 0;
}

T4 是 CF1073E Segment Sum。一眼数位dp。但又不会写。于是骗分。

T5 是 LibreOJ #6039「NAIPC2016」Jewel Thief,骗分。

最后看回T1。真的傻了。直接敲个记搜。应该能过。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,a[2005][2005];
inline int read() {
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
	return x*f;
}
int dp[2005][2005];
int qwq(int x,int y){
	if(dp[x][y]) return dp[x][y];
	int qans=0;
	if(x+1<=n&&a[x+1][y]<a[x][y]) qans=max(qans,qwq(x+1,y));
	if(x-1>=1&&a[x-1][y]<a[x][y]) qans=max(qans,qwq(x-1,y));
	if(y+1<=m&&a[x][y+1]<a[x][y]) qans=max(qans,qwq(x,y+1));
	if(y-1>=1&&a[x][y-1]<a[x][y]) qans=max(qans,qwq(x,y-1));
	return dp[x][y]=qans+1;
}
signed main(){
	freopen("chino.in","r",stdin);
	freopen("chino.out","w",stdout);
	n=read(); m=read();
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			a[i][j]=read();
		}
	}
	int qaq=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(dp[i][j]) qaq=max(qaq,dp[i][j]);
			else qaq=max(qaq,qwq(i,j));
		}
	}
	cout<<qaq<<endl;
	return 0;
}

预计得分:[70,100]+100+100+20+10=[300,330]

实际得分:100+100+100+20+0=320

暴力打错了。于是 班rk5 总rk19/59。

posted @ 2024-07-24 08:26  HAM_qwq  阅读(53)  评论(0编辑  收藏  举报