短学期 动态规划(背包、线性)

拓扑排序:

queue<int>q;
//priority_queue<int,vector<int>,greater<int>>q;
//优先队列的话,会按照数值大小有顺序的输出
//此处为了理解,暂时就用简单队列
inttopo()
{
    for(inti=1;i<=n;i++)
    {
        if(indegree[i]==0)
        {
            q.push(i);
        }
    }
 
    int temp;
    while(!q.empty())
    {
        temp=q.front();//如果是优先队列,这里可以是top()
        printf("%d->",temp);
        q.pop();
        for(inti=1;i<=n;i++)//遍历从temp出发的每一条边,入度--
        {
            if(map[temp][i])
            {
                indegree[i]--;
                if(indegree[i]==0)q.push(i);
            }
        }
    }
}

https://www.luogu.com.cn/problem/P4017(食物链)

#include<iostream>
#define Re register//能少些一堆register
#define Mod 80112002
using namespace std;
const int N = 5005;
int n, m, du[N], inu[N];
int ans, sa[N];
int head[N * 100], cnt;
struct ed {
    int to, nex;
}edge[N * 100];
inline void add(int x, int y) {
    cnt++;
    edge[cnt].to = y;
    edge[cnt].nex = head[x];
    head[x] = cnt;
}
void in(int& read) {
    int x = 0; char ch = getchar();
    while (ch < '0' || ch>'9')ch = getchar();
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    read = x;
}
int dfs(int st) {
    if (!du[st])return 1;
    if (sa[st])return sa[st];
    int sum = 0;
    for (Re int i = head[st]; i; i = edge[i].nex)
        sum = (sum + dfs(edge[i].to)) % Mod;//每加一个数就%一次
    sa[st] = sum % Mod;
    return sa[st];
}
int main() {
    in(n); in(m);
    int a, b;
    for (Re int i = 1; i <= m; i++) {
        in(a); in(b);
        inu[b]++; du[a]++;
        add(a, b);
    }
    for (Re int i = 1; i <= n; i++)
        if (!inu[i])ans = (ans + dfs(i)) % Mod;
    printf("%d\n", ans);
    return 0;
}

https://www.luogu.com.cn/problem/P1233

#include<iostream>
#include<algorithm>
using namespace std;
# define maxN 50005
struct Stick {
	int l, w;
}stick[maxN];
// 首先定义一个名字为 Stick 的结构体,存放木棍的长度和宽度.
int n, dp[maxN];
// 然后定义木棍的数量 n 和 dp 数组.
bool cmp(Stick, Stick);
// 这是排序函数.
int main() {
	//	freopen("1.in", "r", stdin);
	cin >> n;
	for (int i = 1; i <= n; ++i)
		cin >> stick[i].l >> stick[i].w;
	sort(stick + 1, stick + 1 + n, cmp);
	// 输入数据,排序.
	dp[1] = stick[1].w;
	// dp 数组的初始化.
	int k = 1; // 答案最小也为 1.
	for (int i = 2, j; i <= n; ++i) {
		//j = lower_bound(dp + 1, dp + k + 1, stick[i].w) - dp;
		//j <= k ? dp[j] = stick[i].w : dp[++k] = stick[i].w;
		//跑一遍最长上升子序列.
		if (dp[k] <= stick[i].w) {
			dp[++k] = stick[i].w;
		}
		else {
			*lower_bound(dp + 1, dp + k + 1, stick[i].w) = stick[i].w;
		}
	}
	cout << k << '\n';
	// 输出答案.
}
bool cmp(Stick a, Stick b) {
	if (a.l != b.l) return a.l > b.l; // 如果两根木棍的长度不等,那么按木棍的长度从大到小排序.
	return a.w > b.w; // 否则按木棍的宽度从大到小排序.
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值