poj 1155 输入输出问题

本文解析了一道关于树形背包的问题,通过DP方法求解电视台播放比赛中如何最大化收益的同时保证不亏损。文章分享了实现过程及调试经验,包括输入处理的细节调整。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://acm.hust.edu.cn/vjudge/problem/16417

 

重做了一遍poj 1155

 

 

题目大意:给定一棵树,1为根结点表示电视台,有m个叶子节点表示客户,有n-m-1个中间节点表示中转站,每条树边有权值。现在要在电视台播放一场比赛,每个客户愿意花费cost[i]的钱观看,而从电视台到每个客户也都有个费用,并且经过一条边只会产生一个费用。问电视台不亏损的情况最多有几个客户可以看到比赛?1<=n<=1000,1<=m<=n-1;

 

树形背包问题,对于一个树的dp,可以从子节点入手,分析子节点和根节点关系,得到状态转移方程

之前做的:http://www.cnblogs.com/qlky/p/5650783.html

 

重做的时候遇到了一点问题,居然出现了Output Limit Exceeded。原因在这一行:

while(~sf("%d%d",&n,&m),m+n)

我沿用上一道题的表达式,这样写在这题是错的,正确的写法是

while(~sf("%d%d",&n,&m))

或者

while(~sf("%d%d",&n,&m) && n+m)

 

按照题意,n>=2,m>=1,第一个逗号表达式的值是m+n的值,可能是负数,0或正数。

 

while只有在条件等于0时会结束,也就是m+n等于0时结束,题目并没有这么要求,所以不能在这里这么用

 

贴一下完整代码:

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <cctype>
#include <vector>
#include <iterator>
#include <set>
#include <map>
#include <sstream>
using namespace std;

#define mem(a,b) memset(a,b,sizeof(a))
#define pf printf
#define sf scanf
#define spf sprintf
#define pb push_back
#define debug printf("!\n")
#define MAXN 3000+5
#define MAX(a,b) a>b?a:b
#define blank pf("\n")
#define LL long long
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define pqueue priority_queue
#define INF 0x3f3f3f3f

#define ls (rt<<1)
#define rs (rt<<1|1)

int n,m;

int head[MAXN],vis[MAXN],ptr=1;

int num[MAXN],dp[MAXN][MAXN],tmp[MAXN];

struct node{int y,next,val;}tree[MAXN<<2];

void init()
{
    mem(head,-1);
    mem(vis,0);
    ptr = 1;
}

void add(int son,int fa,int val)
{
    tree[ptr].y=son;
    tree[ptr].val=val;
    tree[ptr].next=head[fa];
    head[fa]=ptr++;
}

void dfs(int rt)
{
    vis[rt] = 1;
    for(int i=head[rt];i!=-1;i=tree[i].next)
    {
        int y = tree[i].y;
        if(vis[y]) continue;
        dfs(y);
        for(int j=0;j<=num[rt];j++) tmp[j] = dp[rt][j];
        for(int j=0;j<=num[rt];j++)
        {
            for(int k=1;k<=num[y];k++)
            {
                dp[rt][j+k] = max(dp[rt][j+k],tmp[j]+dp[y][k]-tree[i].val);
            }
        }
        num[rt]+=num[y];
    }
}


int main()
{
    int i,j,k;
    while(~sf("%d%d",&n,&m))
    {
        init();
        for(i=1;i<=n-m;i++)
        {
            num[i] = 0;
            sf("%d",&k);
            for(j=0;j<k;j++)
            {
                int x,y;
                sf("%d%d",&x,&y);
                add(i,x,y);
                add(x,i,y);
            }
        }
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++) dp[i][j] = -10000000;
        }

        for(i=n-m+1;i<=n;i++)
        {
            num[i] = 1;
            sf("%d",&dp[i][1]);
        }
        dfs(1);
        for(i=m;i>=0;i--)
        {
            if(dp[1][i]>=0)
            {
                pf("%d\n",i);
                break;
            }
        }
    }
}

 

转载于:https://www.cnblogs.com/qlky/p/5803288.html

一、综合实战—使用极轴追踪方式绘制信号灯 实战目标:利用对象捕捉追踪和极轴追踪功能创建信号灯图形 技术要点:结合两种追踪方式实现精确绘图,适用于工程制图中需要精确定位的场景 1. 切换至AutoCAD 操作步骤: 启动AutoCAD 2016软件 打开随书光盘中的素材文件 确认工作空间为"草图与注释"模式 2. 绘图设置 1)草图设置对话框 打开方式:通过"工具→绘图设置"菜单命令 功能定位:该对话框包含捕捉、追踪等核心绘图辅助功能设置 2)对象捕捉设置 关键配置: 启用对象捕捉(F3快捷键) 启用对象捕捉追踪(F11快捷键) 勾选端点、中心、圆心、象限点等常用捕捉模式 追踪原理:命令执行时悬停光标可显示追踪矢量,再次悬停可停止追踪 3)极轴追踪设置 参数设置: 启用极轴追踪功能 设置角度增量为45度 确认后退出对话框 3. 绘制信号灯 1)绘制圆形 执行命令:"绘图→圆→圆心、半径"命令 绘制过程: 使用对象捕捉追踪定位矩形中心作为圆心 输入半径值30并按Enter确认 通过象限点捕捉确保圆形位置准确 2)绘制直线 操作要点: 选择"绘图→直线"命令 捕捉矩形上边中点作为起点 捕捉圆的上象限点作为终点 按Enter结束当前直线命令 重复技巧: 按Enter可重复最近使用的直线命令 通过圆心捕捉和极轴追踪绘制放射状直线 最终形成完整的信号灯指示图案 3)完成绘制 验证要点: 检查所有直线是否准确连接圆心和象限点 确认极轴追踪的45度增量是否体现 保存绘图文件(快捷键Ctrl+S)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值