Algorithms Weekly 3

An April Fool's week

  • Jordan Smiley(April Fools Day Contest 2020 E)
    给你一张图片,判断\((x,y)\)是否在脸里面。。
  • step1:
    利用画图工具将闭合区域填充:
  • step2:
    用pillow库将图片转为单通道图片并转为矩阵。
from PIL import Image
import numpy as np
path=r"B.png"

im = Image.open(path).convert('L') #三通道转多通道
width = im.size[0]   # 获取宽度
height = im.size[1]   # 获取高度
im2 = im.resize((int(width*1/15), int(height*1/15)), Image.ANTIALIAS)# 缩小15倍
a=np.array(im2)
np.savetxt("1.txt",a)# 颜色矩阵

得到矩阵后,如果\((i,j)\)处小于等于\(128\),设置为\(1\),否则为0,判断\((x,y)\)处是\(0\)还是\(1\)即可。

  • 学军信友队趣味网络邀请赛
    Final standing:
  • T1是一道巧妙的构造题。

    对于上面的图,输出遍历完所有点的最短时间以及方案,其中最外圈是单向的,箭头所指即为方向,其余对角线之间的道路都是双向的,长度均为1。
    可以肯定最短时间是\((n \cdot (n+1))-1\)
    对于奇偶我们采用不同的方法讨论,以\(n=4\)\(n=5\)为例。

    \(n=4\)的解法

    \(n=5\)的解法
    对于\(n\)为其他数字的情况,和\(n=4,5\)的构造方法类似,奇偶讨论即可。
/*
* @author:  codancer
* @createTime:  2020-04-05, 13:23:23
*/
#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
#define pb push_back
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define fep(i,a,b) for(int i=(a);i>=(b);i--)
typedef vector<int> VI;
typedef vector<ll> VII;
typedef pair<int,int> pii;
int main(){
	int n;
	cin>>n;
	cout<<n*(n+1)-1<<endl;
	if(n%2==0){
		for(int i=n;i>=1;i--) cout<<i<<' '<<1<<endl;
		for(int j=2;j<=n+1;j++){
			if(j%2==0){
				for(int i=1;i<=n;i++){
					if(i&1) cout<<i<<' '<<j<<endl;
					else cout<<i<<' '<<j+1<<endl;
				}
			}else{
				for(int i=n;i>=1;i--){
					if(i&1) cout<<i<<' '<<j<<endl;
					else cout<<i<<' '<<j-1<<endl;
				}
			}
		}
	}else{
		for(int j=1;j<=n+1;j++) cout<<1<<' '<<j<<endl;
		for(int i=2;i<=n;i++){
			if(i%2==0){
				for(int j=n+1;j>=1;j--){
					if(j%2==0){
						cout<<i<<' '<<j<<endl;
					}else{
						cout<<i+1<<' '<<j<<endl;
					}
				}
			}else{
				for(int j=1;j<=n+1;j++){
					if(j&1){
						cout<<i-1<<' '<<j<<endl;
					}else{
						cout<<i<<' '<<j<<endl;
					}
				}
			}
		}
	}
	return 0;
}
  • T2是一个常见的的树形dp,即计算一棵树中每个节点所能到达的最远距离。
    \(f[i][0]\)\(i\)向下走能走到的最远距离,\(f[i][1]\)是次远距离,同时记录最远距离所经过的子节点,令\(f[i][2]\)代表最终答案,
    假设\(v\)经过了\(u\)向下走的最大路径,那么\(f[v][2]=max(f[u][2],f[u][1])+1\),否则\(f[v][2]=max(f[u][2],f[u][0])+1\)
    两次\(DFS\)转移即可。
/*
* @author:  codancer
* @createTime:  2020-04-05, 13:46:51
*/
#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
#define pb push_back
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define fep(i,a,b) for(int i=(a);i>=(b);i--)
typedef vector<int> VI;
typedef vector<ll> VII;
typedef pair<int,int> pii;
const int N = 300000;
vector<int> G[N];
ll f[N][3];
ll node[N];
bool vis[N];
void dfs(int u,int fa){
	for(int v:G[u]){
		if(v==fa) continue;
		dfs(v,u);
		if(f[u][0]<=f[v][0]+1){
			f[u][1]=f[u][0];
			f[u][0]=f[v][0]+1;
			node[u]=v;
		}else if(f[u][1]<f[v][0]+1){
			f[u][1]=f[v][0]+1;
		}
	}
}
void dfs2(int u,int fa){
	for(int v:G[u]){
		if(v==fa) continue;
		if(node[u]==v){
			f[v][2]=max(f[u][2],f[u][1])+1;
		}else{
			f[v][2]=max(f[u][2],f[u][0])+1;
		}
		dfs2(v,u);
	}
}
int main(){
	int n;
	scanf("%d",&n);
	vector<ll> w(n+1);
	rep(i,1,n){
		scanf("%lld",&w[i]);
	}
	int u,v;
	rep(i,1,n-1){
		scanf("%d %d",&u,&v);
		G[v].pb(u);
		G[u].pb(v);
	}
	dfs(1,-1);
	dfs2(1,-1);
	ll ans=0;
	rep(i,1,n){
		ans=max(ans,w[i]*max(f[i][2],f[i][0]));
	}
	cout<<ans<<endl;
	return 0;
}
  • 2020算法首届算法竞赛网络挑战赛
    Final result:
  • 30-Day LeetCoding Challenge
    前面的题目较为简单,不再赘述。
posted @ 2020-04-03 18:31  codancer  阅读(49)  评论(0编辑  收藏