队内胡策的某些题

其实胡策已经一周了,也不按时间顺序放了,挑一些题目放上来,也当做复习

Day1、T2
这个题的原题在洛谷上有P1550 [USACO08OCT]浇水洞Watering Hole

题目描述
众所周知,dqs因上课不好好睡觉被班主任请回了家里!
dqs回到家发现家里还有农场,于是他决定种些什么,几个月后dqs发现好像没有水的话植物并不能活下来╮(╯▽╰)╭
于是dqs决定将水引入到他的边长为n的农场。他准备通过挖若干井,并在各块田中修筑水道来连通各块田地以供水。在第i 号田中挖一口井需要花费W_i元。连接i 号田与j 号田需要P_ij 元。
请求出dqs需要为连通整个农场场的每一块田地所需要的钱数。
输入描述 第1 行为一个整数n。
第2行n个整数,分别为W_1 到W_n。
第3 到n + 2 行为一个矩阵,表示需要的经费P_ij。
输出描述 只有一行,为一个整数,表示所需要的钱数。
样例输入 4
5 4 4 3
0 2 2 2
2 0 3 3
2 3 0 4
2 3 4 0
样例输出 9
数据范围及提示 对于 30 % 的数据:1 <= n <= 5 , 1 <= P_ij , W_i <=100;
对于 60 % 的数据:1 <= n <= 50 , 1 <= P_ij , W_i <= 5000;
对于 100 % 的数据:1 <= n <= 300 , 1 <= P_ij , W_i <= 100000;
样例解释:在第4号田挖井,花费3,连接 1 – 2号田,花费2,连接1 – 4号田,花费 2 ,连接 1 – 3,花费2,总花费9.

/*
这个题的思路是,建立一个虚拟节点0号节点,把0号节点与所有节点连一条边,
权值是挖这个井的花费,因为我们在连接某个农场的时候,可能遇到联通两个农田的花费比在这个地方挖一口井的花费要高,
这种情况下,我们就可以连0号节点与该节点的边,而不是当前节点与该节点的边,这样跑一遍
kruskal,求最小生成树就行了。
*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int n,w[500];
int fa[500000];
struct edge
{
    int x,y,v;
}e[500000];
bool cmp(edge a,edge b)
{
    return a.v <  b.v ;
}
int find(int x)
{
    return fa[x] == x?x:fa[x] = find(fa[x]);
}
int main()
{

    scanf("%d",&n);
        int k,tot = 0;
    for(int i = 1; i <= n; i ++)
    {
        scanf("%d",&w[i]);
        ++tot;
        e[tot].x = 0;
        e[tot].y = i;
        e[tot].v = w[i];
    }
    for(int i = 1; i <= n; i ++)
    fa[i] = i;
    for(int i = 1; i <= n; i ++)
    for(int j = 1; j <= n; j ++)
    {
        scanf("%d",&k);
        ++tot;
        e[tot].x = i;
        e[tot].y = j;
        e[tot].v = k;
    }
    sort(e+1,e+tot,cmp);
    int ans = 0;
    for(int i = 1; i <= n*n ; i ++)
    {
        int p = find(e[i].x);
        int q = find(e[i].y);
        if(p != q)
        {
            fa[p] = q;
            ans += e[i].v;
        }
    }
    printf("%d\n",ans);

    return 0;
}

Day2、T3
这个题是我从hdu上找的,出给他们,让他们复习下背包问题。
原题HDU5410CRB and His Birthday
这是个混合背包问题,我是用01背包和完全背包做的。

#include<iostream>  
#include<algorithm>  
#include<cstring>  
#include<cstdio>  
#include<queue>  
using namespace std;
const int MAXN = 1000010;
int dp[MAXN];  
int c[MAXN],a[MAXN],b[MAXN];  
int V,n;
int main()  
{  
    int i,t;
    cin >>t;
    while(t--)
    {
        cin>>V>>n;
        for(i=1;i<=n;i++)  
        {  
            cin>>c[i]>>a[i]>>b[i];
        }  
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)  //01
        {  
            for(int j=V;j>=c[i];j--)  
            {  
                dp[j]=max(dp[j],dp[j-c[i]]+a[i]+b[i]);  
            }  
        } 
        for(int i=1;i<=n;i++)  //完全 
        {  
            for(int j=c[i];j<=V;j++)  
            {  
                dp[j]=max(dp[j],dp[j-c[i]]+a[i]);    
            }     
        }     
        printf("%d\n",dp[V]);  
    }    
    return 0;  
 }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值