C++——USACO Section 3.1 题解

44 篇文章 0 订阅
Agri-Net
Russ Cox

Farmer John has been elected mayor of his town! One of his campaign promises was to bring internet connectivity to all farms in the area. He needs your help, of course.

Farmer John ordered a high speed connection for his farm and is going to share his connectivity with the other farmers. To minimize cost, he wants to lay the minimum amount of optical fiber to connect his farm to all the other farms.

Given a list of how much fiber it takes to connect each pair of farms, you must find the minimum amount of fiber needed to connect them all together. Each farm must connect to some other farm such that a packet can flow from any one farm to any other farm.

The distance between any two farms will not exceed 100,000.

PROGRAM NAME: agrinet

INPUT FORMAT

Line 1:The number of farms, N (3 <= N <= 100).
Line 2..end:The subsequent lines contain the N x N connectivity matrix, where each element shows the distance from on farm to another. Logically, they are N lines of N space-separated integers. Physically, they are limited in length to 80 characters, so some lines continue onto others. Of course, the diagonal will be 0, since the distance from farm i to itself is not interesting for this problem.

SAMPLE INPUT (file agrinet.in)

4
0 4 9 21
4 0 8 17
9 8 0 16
21 17 16 0

OUTPUT FORMAT

The single output contains the integer length that is the sum of the minimum length of fiber required to connect the entire set of farms.

SAMPLE OUTPUT (file agrinet.out)

28

/*
ID: mcdonne1
PROG: agrinet
LANG: C++
*/
#include<cstdio>
bool u[1001];
int minn[1001],g[1001][1001];
int main()
{
	freopen("agrinet.in","r",stdin);
	freopen("agrinet.out","w",stdout);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			scanf("%d",&g[i][j]);
	for(int i=0;i<=1000;i++) minn[i]=100000000;
	minn[1]=0;
	for(int i=0;i<=1000;i++) u[i]=true;
	for(int i=1;i<=n;i++)
	{
		register int k=0;
		for(int j=1;j<=n;j++) if(u[j]==true&&minn[j]<minn[k]) k=j;
		u[k]=false;
		for(int j=1;j<=n;j++) if(u[j]==true&&g[k][j]<minn[j]) minn[j]=g[k][j];
	}
	int total=0;
	for(int i=1;i<=n;i++) total=total+minn[i];
	printf("%d\n",total);
	return 0;
}

Score Inflation

The more points students score in our contests, the happier we here at the USACO are. We try to design our contests so that people can score as many points as possible, and would like your assistance.

We have several categories from which problems can be chosen, where a "category" is an unlimited set of contest problems which all require the same amount of time to solve and deserve the same number of points for a correct solution. Your task is write a program which tells the USACO staff how many problems from each category to include in a contest so as to maximize the total number of points in the chosen problems while keeping the total solution time within the length of the contest.

The input includes the length of the contest, M (1 <= M <= 10,000) (don't worry, you won't have to compete in the longer contests until training camp) and N, the number of problem categories, where 1 <= N <= 10,000.

Each of the subsequent N lines contains two integers describing a category: the first integer tells the number of points a problem from that category is worth (1 <= points <= 10000); the second tells the number of minutes a problem from that category takes to solve (1 <= minutes <= 10000).

Your program should determine the number of problems we should take from each category to make the highest-scoring contest solvable within the length of the contest. Remember, the number from any category can be any nonnegative integer (0, one, or many). Calculate the maximum number of possible points.

PROGRAM NAME: inflate

INPUT FORMAT

Line 1:M, N -- contest minutes and number of problem classes
Lines 2-N+1:Two integers: the points and minutes for each class

SAMPLE INPUT (file inflate.in)

300 4
100 60
250 120
120 100
35 20

OUTPUT FORMAT

A single line with the maximum number of points possible given the constraints.

SAMPLE OUTPUT (file inflate.out)

605
(Take two problems from #2 and three from #4.)  
/*
ID: mcdonne1
PROG: inflate
LANG: C++
*/
#include<cstdio>
#include<algorithm>
using namespace std;
int m,n;
int time[10001],score[10001];
int f[10001]={1};
int main()
{
	freopen("inflate.in","r",stdin);
	freopen("inflate.out","w",stdout);
	scanf("%d%d",&m,&n);
	for(int i=1;i<=n;++i) scanf("%d%d",&score[i],&time[i]);
	for(int i=1;i<=n;++i)
		for(int j=time[i];j<=m;++j)
			if(f[j-time[i]])
				f[j]=max(f[j],f[j-time[i]]+score[i]);
	sort(f,f+1+m);
	printf("%d\n",f[m]-1);
	return 0;
}
Humble Numbers

For a given set of K prime numbers S = {p1, p2, ..., pK}, consider the set of all numbers whose prime factors are a subset of S. This set contains, for example, p1, p1p2, p1p1, and p1p2p3 (among others). This is the set of `humble numbers' for the input set S. Note: The number 1 is explicitly declared not to be a humble number.

Your job is to find the Nth humble number for a given set S. Long integers (signed 32-bit) will be adequate for all solutions.

PROGRAM NAME: humble

INPUT FORMAT

Line 1:Two space separated integers: K and N, 1 <= K <=100 and 1 <= N <= 100,000.
Line 2:K space separated positive integers that compose the set S.

SAMPLE INPUT (file humble.in)

4 19
2 3 5 7

OUTPUT FORMAT

The Nth humble number from set S printed alone on a line.

SAMPLE OUTPUT (file humble.out)

27
/*
ID: mcdonne1
PROG: humble
LANG: C++
*/
#include<cstdio>
int n,k,now;
int a[100001],ans[100001]={1},s[100001];
inline int min(int a,int b)
{
	return a < b ? a : b ;
}
int main()
{
	freopen("humble.in","r",stdin);
	freopen("humble.out","w",stdout);
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;++i) scanf("%d",&a[i]);
	for(int i=1;i<=k;++i)
	{
		now=0x7fffffff;
		for(int j=1;j<=n;++j)
		{
			while(a[j]*ans[s[j]]<=ans[i-1]) s[j]++;
			now=min(now,a[j]*ans[s[j]]);
		}
		ans[i]=now;
	}
	printf("%d\n",ans[k]);
	return 0;
}
Contact
IOI'98

The cows have developed a new interest in scanning the universe outside their farm with radiotelescopes. Recently, they noticed a very curious microwave pulsing emission sent right from the centre of the galaxy. They wish to know if the emission is transmitted by some extraterrestrial form of intelligent life or if it is nothing but the usual heartbeat of the stars.

Help the cows to find the Truth by providing a tool to analyze bit patterns in the files they record. They are seeking bit patterns of length A through B inclusive (1 <= A <= B <= 12) that repeat themselves most often in each day's data file. They are looking for the patterns that repeat themselves most often. An input limit tells how many of the most frequent patterns to output.

Pattern occurrences may overlap, and only patterns that occur at least once are taken into account.

PROGRAM NAME: contact

INPUT FORMAT

Line 1:Three space-separated integers: A, B, N; (1 <= N ≤ 50)
Lines 2 and beyond:A sequence of as many as 200,000 characters, all 0 or 1; the characters are presented 80 per line, except potentially the last line.

SAMPLE INPUT (file contact.in)

2 4 10
01010010010001000111101100001010011001111000010010011110010000000

In this example, pattern 100 occurs 12 times, and pattern 1000 occurs 5 times. The most frequent pattern is 00, with 23 occurrences.

OUTPUT FORMAT

Lines that list the N highest frequencies (in descending order of frequency) along with the patterns that occur in those frequencies. Order those patterns by shortest-to-longest and increasing binary number for those of the same frequency. If fewer than N highest frequencies are available, print only those that are.

Print the frequency alone by itself on a line. Then print the actual patterns space separated, six to a line (unless fewer than six remain).

SAMPLE OUTPUT (file contact.out)

23
00
15
01 10
12
100
11
11 000 001
10
010
8
0100
7
0010 1001
6
111 0000
5
011 110 1000
4
0001 0011 1100
/*
ID: mcdonne1
PROG: contact
LANG: C++
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a,b,n,cnt;
int time[20][5000];
char s[200005];
struct node{
	int time,v,len;
}e[100000];
inline int gain(int e,int len)
{
	int ans=0;
	for(int i=0;i<len;++i)
		ans=ans*2+(s[e+i]=='1');
	return ans;
}
inline void print(int v,int len)
{
	char s[20]="";
	for(int i=len-1;i>=0;--i)
	{
		s[i]=v%2+'0';
		v/=2;
	}
	printf("%s",s);
}
inline bool cmp(node a,node b)
{
	return a.time > b.time || a.time == b.time && (a.len < b.len || a.len == b.len && a.v < b.v);
}
int main()
{
	freopen("contact.in","r",stdin);
	freopen("contact.out","w",stdout);
	scanf("%d%d%d",&a,&b,&n);
	while(~scanf("%s",s+strlen(s)));
	int l=strlen(s);
	for(int i=0;i<l-a+1;++i)
		for(int j=a;j<=b&&i+j<=l;++j)
			++time[j][gain(i,j)];
	for(int i=a;i<=b;++i)
		for(int j=0;j<1<<i;++j)
			if(time[i][j])
				e[cnt++]=(node){time[i][j],j,i};
	sort(e,e+cnt,cmp);
	int num;
	for(int i=0,j=0;i<cnt;++i)
	{
		if(!i||e[i].time!=e[i-1].time)
		{
			++j;
			if(j>n) break;
			printf("%d\n",e[i].time);
			num=0;
		}
		print(e[i].v,e[i].len);
		++num;
		e[i].time==e[i+1].time&&num%6 ? putchar(' ') : putchar('\n');
	}
	return 0;
}
Stamps

Given a set of N stamp values (e.g., {1 cent, 3 cents}) and an upper limit K to the number of stamps that can fit on an envelope, calculate the largest unbroken list of postages from 1 cent to M cents that can be created.

For example, consider stamps whose values are limited to 1 cent and 3 cents; you can use at most 5 stamps. It's easy to see how to assemble postage of 1 through 5 cents (just use that many 1 cent stamps), and successive values aren't much harder:

  • 6 = 3 + 3
  • 7 = 3 + 3 + 1
  • 8 = 3 + 3 + 1 + 1
  • 9 = 3 + 3 + 3
  • 10 = 3 + 3 + 3 + 1
  • 11 = 3 + 3 + 3 + 1 + 1
  • 12 = 3 + 3 + 3 + 3
  • 13 = 3 + 3 + 3 + 3 + 1.

However, there is no way to make 14 cents of postage with 5 or fewer stamps of value 1 and 3 cents. Thus, for this set of two stamp values and a limit of K=5, the answer is M=13.

The most difficult test case for this problem has a time limit of 3 seconds.

PROGRAM NAME: stamps

INPUT FORMAT

Line 1:Two integers K and N. K (1 <= K <= 200) is the total number of stamps that can be used. N (1 <= N <= 50) is the number of stamp values.
Lines 2..end:N integers, 15 per line, listing all of the N stamp values, each of which will be at most 10000.

SAMPLE INPUT (file stamps.in)

5 2
1 3

OUTPUT FORMAT

Line 1:One integer, the number of contiguous postage values starting at 1 cent that can be formed using no more than K stamps from the set.

SAMPLE OUTPUT (file stamps.out)

13
/*
ID: mcdonne1
PROG: stamps
LANG: C++
*/
#include<cstdio>
#include<algorithm>
#define min(a,b) (a)<(b)?(a):(b)
int k,n;
int val[51],used[2000100];
bool f[2000100];
int main()
{
	freopen("stamps.in","r",stdin);
	freopen("stamps.out","w",stdout);
	scanf("%d%d",&k,&n);
	for(int i=1;i<=n;++i) scanf("%d",&val[i]);
	std::sort(val+1,val+1+n);
	f[0]=true;
	for(int i=1;i<=n;++i)
		for(int j=val[i];j<=k*val[n];++j)
			if(f[j-val[i]])
			{
				f[j] ? used[j]=min(used[j],used[j-val[i]]+1) : used[j]=used[j-val[i]]+1;
				f[j]=true;
			}
	for(int i=1;;++i)
		if(!f[i]||used[i]>k)
		{
			printf("%d\n",i-1);
			return 0;
		}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值