其实胡策已经一周了,也不按时间顺序放了,挑一些题目放上来,也当做复习
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;
}