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
    前面的题目较为简单,不再赘述。
原文地址:https://www.cnblogs.com/codancer/p/12619166.html