【算法刷题日记第二篇】Codeforces Round 785 (Div. 2) C && Leetcode1334

Codeforces Round 785 (Div. 2) C && Leetcode1334

题目及来源

  1. 题目来源: 11月14日灵茶试炼 && 力扣每日一题

  2. 题目链接:
    codeforces Round 785 (Div. 2) C
    Leetcode 1334

  3. codeforces题目描述:
    给你一个正整数 n n n 。如果某个不带前导零的正整数 a a a 的数位顺序颠倒后仍然不变,我们就称它为回折正整数 a a a 。求把 n n n 表示成正整数宫调整数之和的不同方法的数目。如果两种表达方式中至少有一个回折整数的频率不同,那么这两种表达方式就被认为是不同的。例如, 5 = 4 + 1 5=4+1 5=4+1 5 = 3 + 1 + 1 5=3+1+1 5=3+1+1 被认为是不同的,但 5 = 3 + 1 + 1 5=3+1+1 5=3+1+1 5 = 1 + 3 + 1 5=1+3+1 5=1+3+1 被认为是相同的。
    从形式上看,你需要找出正宫调整数的和等于 n n n 的不同多集的个数。
    由于答案可能很大,请打印出以 1 0 9 + 7 10^9+7 109+7 为模数的答案。
    输入
    第一行输入包含一个整数 t t t ( 1 ≤ t ≤ 1 0 4 1\leq t\leq 10^4 1t104 ),表示测试用例的数量。
    每个测试用例都包含一行输入,其中包含一个整数 n n n ( 1 ≤ n ≤ 4 ⋅ 1 0 4 1\leq n\leq 4\cdot 10^4 1n4104 ) - 所需的回文整数之和。
    输出
    为每个测试用例打印一个整数,表示所需的答案取模 1 0 9 + 7 10^9+7 109+7

  4. Leetcode题目描述:
    有 n 个城市,按从 0 到 n-1 编号。给你一个边数组 edges,其中 edges[i] = [fromi, toi, weighti] 代表 fromi 和 toi 两个城市之间的双向加权边,距离阈值是一个整数 distanceThreshold。
    返回能通过某些路径到达其他城市数目最少、且路径距离 最大 为 distanceThreshold 的城市。如果有多个这样的城市,则返回编号最大的城市。
    注意,连接城市 i 和 j 的路径的距离等于沿该路径的所有边的权重之和。

codeforces 题目思路

可以将回文数字预处理出来,处理方法就是将每一个数字都生成它的回文,由数据范围可知预处理的数字最大不超过400,之后将这些回文数字进行一个完全背包的过程。
预处理数字的值为m
时间复杂度: O ( n ∗ m ) O(n * m) O(nm)
空间复杂度: O ( n + m ) O(n + m) O(n+m)

Leetcode 题目思路

可以使用多源最短路算法floyd算法,或者使用单源最短路dijkstra算法跑多次,floyd算法和灵神学到了dp的思路,
d f s ( k , i , j ) dfs(k, i, j) dfs(k,i,j) 定义为中间节点小于等于k的i到j的距离
d f s ( k , i , j ) = m i n ( d f s ( k − 1 , i , k ) , d f s ( k − 1 , i , k ) + d f s ( k − 1 , k , j ) ) dfs(k, i, j) = min(dfs(k - 1, i, k), dfs(k - 1, i, k) + dfs(k - 1, k, j)) dfs(k,i,j)=min(dfs(k1,i,k),dfs(k1,i,k)+dfs(k1,k,j))
时间复杂度: O ( n 3 ) O(n^3) O(n3)
空间复杂度: O ( n 2 ) O(n^2) O(n2)

codeforces代码

go语言版本代码

package main

import (
	"bufio"
	"container/heap"
	. "fmt"
	"os"
)

// func init() { debug.SetGCPercent(-1) } // 关闭垃圾收集

func run() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush() // 加速读取
	var t, n int
	var pal []int
	const mod int = 1e9 + 7
	for i := 1; i < 400; i++ {
		p := i
		for x := i / 10; x > 0; x /= 10 {
			p = p*10 + x%10
		}
		pal = append(pal, p)
		if i < 100 {
			p := i
			for x := i; x > 0; x /= 10 {
				p = p*10 + x%10
			}
			pal = append(pal, p)
		}
	}
	var f [40001]int
	f[0] = 1
	for _, v := range pal {
		for j := v; j < len(f); j++ {
			f[j] = (f[j] + f[j-v]) % mod
		}
	}
	for Fscan(in, &t); t > 0; t-- {
		Fscan(in, &n)
		Fprintln(out, f[n])
	}

}

func main() {
	run()
}

Leetcode代码

go语言版本

// func findTheCity(n int, edges [][]int, distanceThreshold int) (ans int) {
// 	f := make([][]int, n)
// 	for i := range f {
// 		f[i] = make([]int, n)
// 		for j := range f[i] {
// 			f[i][j] = math.MaxInt >> 1
// 		}
// 	}
// 	for _, e := range edges {
// 		x, y, v := e[0], e[1], e[2]
// 		f[x][y] = v
// 		f[y][x] = v
// 	}
// 	for k := 0; k < n; k++ { // floyd算法
// 		for i := 0; i < n; i++ {
// 			for j := 0; j < n; j++ {
// 				f[i][j] = min(f[i][j], f[i][k]+f[k][j])
// 			}
// 		}
// 	}

// 	//var dfs func(int, int, int) int
// 	//dfs = func(k, i, j int) int {
// 	//	if k < 0 {
// 	//		return f[i][j]
// 	//	}
// 	//	p := &f[k][i][j]
// 	//	if *p != 0 {
// 	//		return *p
// 	//	}
// 	//	res := min(dfs(k-1, i, j), dfs(k-1, i, k)+dfs(k-1, k, j))
// 	//	*p = res
// 	//	return res
// 	//}
// 	minCnt := n
// 	for i, dis := range f {
// 		cnt := 0
// 		for j, d := range dis {
// 			if i != j && d <= distanceThreshold {
// 				cnt++
// 			}
// 		}
// 		if cnt <= minCnt {
// 			minCnt = cnt
// 			ans = i
// 		}
// 	}
// 	return
// }
func findTheCity(n int, edges [][]int, distanceThreshold int) (ans int) {
	const inf int = 1e9 + 7
	vis := make([]bool, n)
	dist := make([]int, n)
	g := make([][]int, n)
	for i := range g {
		g[i] = make([]int, n)
		for j := range g[i] {
			g[i][j] = inf
		}
	}
	for _, e := range edges {
		x, y, v := e[0], e[1], e[2]
		g[x][y] = v
		g[y][x] = v
	}
	dijkstra := func(u int) (cnt int) { //朴素的dijkstra
		for i := range vis {
			vis[i] = false
			dist[i] = inf
		}
		dist[u] = 0
		for i := 0; i < n; i++ {
			k := -1
			for j := 0; j < n; j++ {
				if !vis[j] && (k == -1 || dist[j] < dist[k]) {
					k = j
				}
			}
			vis[k] = true
			for j := 0; j < n; j++ {
				dist[j] = min(dist[j], dist[k]+g[k][j])
			}
		}
		for _, d := range dist {
			if d <= distanceThreshold {
				cnt++
			}
		}
		return
	}
	minCnt := n
	for i := 0; i < n; i++ {
		if t := dijkstra(i); t <= minCnt {
			minCnt = t
			ans = i
		}
	}
	return
}

dijkstra堆优化

func findTheCity(n int, edges [][]int, distanceThreshold int) (ans int) {
	const inf int = 1e9 + 7
	dist := make([]int, n)
	g := make([][]pair, n)
	for _, e := range edges {
		x, y, v := e[0], e[1], e[2]
		g[x] = append(g[x], pair{y, v})
		g[y] = append(g[y], pair{x, v})
	}
	dijkstra := func(u int) (cnt int) { //朴素的dijkstra
		for i := range dist {
			dist[i] = inf
		}
		h := hp{}
		heap.Push(&h, pair{u, 0})
		for h.Len() > 0 {
			p := heap.Pop(&h).(pair)
			if dist[p.i] < inf {
				continue
			}
			dist[p.i] =  p.v
			for _, p1 := range g[p.i] {
				if dist[p1.i] == inf {
					heap.Push(&h, pair{p1.i, p1.v + p.v})
				}
			}
		}
		for _, d := range dist {
			if d <= distanceThreshold {
				cnt++
			}
		}
		return
	}
	minCnt := n
	for i := 0; i < n; i++ {
		if t := dijkstra(i); t <= minCnt {
			minCnt = t
			ans = i
		}
	}
	return
}

type pair struct {
	i, v int
}

type hp []pair

func (h *hp) Len() int {
	return len(*h)
}

func (h *hp) Less(i, j int) bool {
	a := *h
	return a[i].v < a[j].v
}

func (h *hp) Swap(i, j int) {
	a := *h
	a[i], a[j] = a[j], a[i]
}

func (h *hp) Push(x any) {
	*h = append(*h, x.(pair))
}

func (h *hp) Pop() any {
	a := *h
	v := a[len(a)-1]
	*h = a[:len(a)-1]
	return v
}

C++版本代码

class Solution {
public:
    int findTheCity(int n, vector<vector<int>>& edges, int distanceThreshold) {
        vector<vector<int>> w(n, vector<int>(n, INT_MAX >> 1));
        for (int i = 0; i < edges.size(); i++) {
            int x = edges[i][0], y = edges[i][1], v = edges[i][2];
            w[x][y] = v, w[y][x] = v;
        }
        auto f = move(w);
        for (int k = 0; k < n; k++) {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
                }
            }
        }
        int minCnt = n - 1, ans = 0;
        for (int i = 0; i < n; i++) {
            int cnt = 0;
            for (int j = 0; j < n; j++) {
                if (i != j && f[i][j] <= distanceThreshold) {
                    cnt++;
                }
            }
            if (cnt <= minCnt) {
                minCnt = cnt;
                ans = i;
            }
        }
        return ans;
    }
};
static int fast_io = [](){ 
    std::ios::sync_with_stdio(false); 
    cin.tie(nullptr); 
    cout.tie(nullptr);
    return 0;
}();
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wby__&&

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值