2014 UESTC Training for Dynamic Programming L

树形DP,除了求出最少需要的次数还需要求出最小次数对应的方案数
dp[u][1]表示u这个点改变为白色,且u这个子树满足条件的最小次数
dp[u][0]表示u这个点不改变且u这棵子树满足条件时的最少次数
转移就是dp[u][1]=
sum(min(dp[vi][1],dp[vi][0]) )+1;
dp[u][0]=sum(dp[vi][1]); 
(v是u的全部子节点)
另外再开一个num数组跟着一起转移就可以
注意转移是要用乘法不是加法,每次叶子节点初始化为num[u][0]=num[u][1]=1;

而且注意最后如果dp[1][0]==dp[1][1].那么ans2=num[1][0]+num[1][1]也要再次取模。这里仍然存在加抄10007的可能性

#include <map>
#include <set>
#include <list>
#include <cmath>
#include<cctype>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b)
{
	return a % b == 0 ? b : gcd(b, a % b);
}
#define MAXN 100005
#define MOD 10007
int dp[MAXN][2];
int num[MAXN][2];
int ans1;LL ans2;
vector <int>vv[MAXN];
int N;
void add(int u,int v)
{
    vv[u].push_back(v);
}
void init()
{
    for (int i=0;i<=N;i++)
        vv[i].clear();
}
void dfs(int u,int fa)
{
    dp[u][0]=0;dp[u][1]=1;
    num[u][0]=1;num[u][1]=1;
    for (int i=0;i<vv[u].size();i++)
    {
        int v=vv[u][i];
        if (v==fa) continue;
        dfs(v,u);
        dp[u][0]+=dp[v][1];
        num[u][0]*=num[v][1];
        num[u][0]%=10007;
        if(dp[v][0]<dp[v][1])
        {
          dp[u][1]+=dp[v][0];
          num[u][1]*=num[v][0];
        }
        else if(dp[v][0]>dp[v][1])
        {
          dp[u][1]+=dp[v][1];
          num[u][1]*=num[v][1];
        }
        else
        {
          dp[u][1]+=dp[v][1];
          num[u][1]*=(num[v][0]+num[v][1]);
        }
         num[u][1]%=10007;
    }
}
void slove()
{
    scanf("%d",&N);
    init();
    int x,y;
    for (int i=1;i<N;i++)
    {
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    dfs(1,-1);
    ans1=min(dp[1][0],dp[1][1]);
    if (dp[1][0]==dp[1][1]) ans2=num[1][0]+num[1][1];
    else if (dp[1][0]>dp[1][1]) ans2=num[1][1];
    else ans2=num[1][0];
   // for (int i=1;i<N;i++) printf("dp[%d][1]=%d   ,dp[%d][0]=%d\n",i,dp[i][1],i,dp[i][0]);
   // for (int i=1;i<=N;i++) printf("nun[%d][1]=%d   ,num[%d][0]=%d\n",i,num[i][1],i,num[i][0]);
    printf("%d %lld\n",ans1,ans2%10007);
}
int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    slove();
    return 0;
}


内容概要:本文围绕“考虑电能交互的冷热电区域多微网系统双层多场景协同优化配置”的Matlab代码实现展开,提出一种结合电能交互机制的双层优化模型,用于解决冷、热、电多能耦合背景下多微网系统的协同规划与运行问题。研究采用多场景分析方法应对可再生能源出力与负荷需求的不确定性,通过上层规划设备容量配置与下层优化多时段运行策略的联动,提升系统在复杂环境下的经济性、鲁棒性与能源利用效率。所提供的Matlab代码集成了建模、求解(如YALMIP+CPLEX)与结果可视化全流程,涵盖场景生成与削减、双层优化结构设计及多能流协同调度等关键技术环节,为综合能源系统优化提供了完整的算法实现与技术参考。; 适合人群:具备电力系统、综合能源系统或优化建模背景,熟悉Matlab编程与数学规划方法,正在从事相关领域科研或工程设计工作的研究生、高校研究人员及能源行业技术人员。; 使用场景及目标:①开展冷热电联供(CCHP)多微网系统的容量规划与运行优化研究;②支撑含分布式能源、储能及多能转换设备的综合能源系统多目标、多场景优化建模;③学习与复现双层优化、分布鲁棒优化及场景分析等先进优化方法在能源系统中的实际应用。; 阅读建议:建议结合配套文献与代码同步研读,重点理解双层模型的构建逻辑、变量耦合关系与求解技巧,关注场景生成方法与YALMIP调用细节,通过调整参数、修改目标函数等方式进行仿真实验,以深化对系统优化机理的掌握。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值