您的位置:首页 > 理论基础 > 计算机网络

第三届华中地区邀请赛网络赛题解

2014-04-16 16:57 309 查看
Problem 1537 - A - Stones I
Time Limit: 1000MS   Memory Limit: 65536KB   

Total Submit: 491  Accepted: 90  Special Judge: No
Description
Xiaoming took the flight MH370 on March 8, 2014 to China to take the ACM contest in WHU. Unfortunately, when the airplane crossing the ocean, a beam of mystical light suddenly lit up the sky and all the passengers with the airplane were transferred to another desert planet.
 
When waking up, Xiaoming found himself lying on a planet with many precious stones. He found that:
 
There are n precious stones lying on the planet, each of them has 2 positive values ai and bi. Each time Xiaoming can take the ith of the stones ,after that, all of the stones’ aj (including the stones Xiaoming has taken) will cut down bi units.
 
Xiaoming could choose arbitrary number (zero is permitted) of the stones in any order. Thus, he wanted to maximize the sum of all the stones he has been chosen. Please help him.
Input
The input consists of one or more test cases.

First line of each test case consists of one integer n with 1 <= n <= 1000.

Then each of the following n lines contains two values ai and bi.( 1<= ai<=1000, 1<= bi<=1000)

Input is terminated by a value of zero (0) for n. 
Output
For each test case, output the maximum of the sum in one line.
Sample Input
1

100 100

3

2 1

3 1

4 1

0
Sample Output
0

3
Hint
Source
 

 

题目大意:有一堆石头,每个石头有ai与bi值,我们每拿起一个石头,所有的石头的ai值都会减去一个bi值,问你拿

石头使得sum最大,sum为所有的ai之和。是减去bi之后的。

 

解题思路:我们可以把问题简化,如果拿起n个石头,那么所有的ai都会减去b1+..+bn值,我们可以直接枚举n,再给

ai-n*bi排个序,选前n个即可,具体见代码。

 

题目地址:http://acm.whu.edu.cn/land/problem/detail?problem_id=1537

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

struct node
{
int a;
int b;
int c;
}nod[1005];

int cmp(node p1,node p2)
{
if(p1.c>=p2.c) return 1;
return 0;
}

int main()
{
int n,i,j;

while(cin>>n&&n)
{
for(i=0;i<n;i++)
scanf("%d%d",&nod[i].a,&nod[i].b);

int ans=0;
for(i=1;i<=n;i++)  //枚举拿起石头的个数
{
for(j=0;j<n;j++)
nod[j].c=nod[j].a-nod[j].b*i;
sort(nod,nod+n,cmp);

int tmp=0;
for(j=0;j<i;j++)
tmp+=nod[j].c;
ans=max(ans,tmp);
}
cout<<ans<<endl;
}

return 0;
}


 

Problem 1538 - B - Stones II
Time Limit: 1000MS   Memory Limit: 65536KB   

Total Submit: 365  Accepted: 49  Special Judge: No
Description
Xiaoming took the flight MH370 on March 8, 2014 to China to take the ACM contest in WHU. Unfortunately, when the airplane crossing the ocean, a beam of mystical light suddenly lit up the sky and all the passengers with the airplane were transferred to another desert planet.
 
When waking up, Xiaoming found himself lying on a planet with many precious stones. He found that:
 
There are n precious stones lying on the planet, each of them has 2 positive values ai and bi. Each time Xiaoming can take the ith of the stones ,after that, all of the stones’ aj (NOT including the stones Xiaoming has taken) will cut down bi units.
 
Xiaoming could choose arbitrary number (zero is permitted) of the stones in any order. Thus, he wanted to maximize the sum of all the stones he has been chosen. Please help him.
Input
The input consists of one or more test cases.

First line of each test case consists of one integer n with 1 <= n <= 1000.

Then each of the following n lines contains two values ai and bi.( 1<= ai<=1000, 1<= bi<=1000)

Input is terminated by a value of zero (0) for n. 
Output
For each test case, output the maximum of the sum in one line.
Sample Input
1

100 100

3

2 1

3 1

4 1

0
Sample Output
100

6
Hint
Source
 

 

题目大意:这题是上一题的升级版,不过区别是每次拿起石头的时候,没有被选到的石头都会减去拿起石头的bj值。

 

解题思路:动态规划题目。如果被选,bi小的肯定被先选。因为,如果某两块石头,bi大的先选了;那么交换

这两块石头的选取顺序,可以得到更大的价值。所以先对bi排个序,然后再dp.

dp[i][j]表示选第i个物品后还要选择j个物品,那么

dp[i][j]=max(dp[i-1][j],dp[i-1][j+1]+a[i]-b[i]*j),

                       不拿第i个         拿第i个            

 

题目地址:http://acm.whu.edu.cn/land/problem/detail?problem_id=1538

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1005;

struct node
{
int a;
int b;
}nod[maxn];

int cmp(node p1,node p2)
{
if(p1.b<p2.b) return 1;
else if(p1.b==p2.b&&p1.a<p2.a) return 1;
return 0;
}

int dp[maxn][maxn];
//dp[i][j]表示选第i个物品后还要选择j个物品
//dp[i][j]=max(dp[i-1][j],dp[i-1][j+1]+a[i]-b[i]*j)
//              不拿第i个        拿第i个

int main()
{
int n,i,j;

while(cin>>n&&n)
{
for(i=1;i<=n;i++)
scanf("%d%d",&nod[i].a,&nod[i].b);

sort(nod+1,nod+n+1,cmp);
memset(dp,0,sizeof(dp));

for(i=1;i<=n;i++)
{
for(j=0;j<n;j++)
dp[i][j]=max(dp[i-1][j],dp[i-1][j+1]+nod[i].a-nod[i].b*j);
}
cout<<dp
[0]<<endl;
}

return 0;
}


 

Problem 1540 - D - Fibonacci
Time Limit: 1000MS   Memory Limit: 65536KB   

Total Submit: 279  Accepted: 49  Special Judge: No
Description
Calculate the sum of the cubes of the first n items in Fibonacci sequence in which the first two are both 1.
Input
The input consists of one or more test cases.

First line of each test case consists only one integer n. (1<=n<=10^9)

Input is terminated by a value of zero (0) for n.
Output
For each test case, output the answer mod 1000000007.
Sample Input
1

2

3
Sample Output
1

2

10
Hint
Source
 

 

题目大意:只要知道cube是三次方就可以了,fibo三次方的前n项和。

 

        解题思路:男神当时就很强的敏感到是矩阵的快速幂,但是当时没找出公式,大一的队伍竟然在网上找到了

公式。。。然后我就误以为是暴力,开始打表。



 

题目地址:http://acm.whu.edu.cn/land/problem/detail?problem_id=1540

 

AC代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#define ll long long
using namespace std;

const int mod = 1e9+7;
ll ans[5][5],bas[5][5],tmp[5][5];

void init()
{
ans[0][0]=ans[0][1]=ans[0][2]=ans[1][1]=ans[1][2]=1;
ans[2][1]=ans[3][1]=ans[3][4]=ans[4][1]=ans[4][3]=1;
ans[1][0]=ans[2][0]=ans[3][0]=ans[4][0]=ans[2][2]=0;
ans[3][2]=ans[4][2]=ans[2][3]=ans[2][4]=ans[4][4]=0;
ans[0][3]=ans[0][4]=ans[1][3]=ans[1][4]=3;
ans[3][3]=2;
int i,j;
for(i=0;i<5;i++)
for(j=0;j<5;j++)
{
bas[i][j]=ans[i][j];
}
}

void cal1()   //n>>=1
{
int i,j,k;
for(i=0;i<5;i++)
{
for(j=0;j<5;j++)
{
tmp[i][j]=bas[i][j];
bas[i][j]=0;
}
}

for(i=0;i<5;i++)
{
for(j=0;j<5;j++)
{
for(k=0;k<5;k++)
{
bas[i][j]=(bas[i][j]+tmp[i][k]*tmp[k][j])%mod;
}
}
}
}

void cal2()   //n&1
{
int i,j,k;
for(i=0;i<5;i++)
{
for(j=0;j<5;j++)
{
tmp[i][j]=ans[i][j];
ans[i][j]=0;
}
}

for(i=0;i<5;i++)
{
for(j=0;j<5;j++)
{
for(k=0;k<5;k++)
{
ans[i][j]=(ans[i][j]+tmp[i][k]*bas[k][j])%mod;
}
}
}
}

int main()
{
int n,i;
while(cin>>n&&n)
{
if(n==1)      {  puts("1"); continue;}
else if(n==2) {  puts("2"); continue;}
n-=3;
init();
while(n)
{
if(n&1) cal2();
cal1();
n>>=1;
}

ll res;
res=2*ans[0][0];
for(i=1;i<5;i++)
res+=ans[0][i];
res=(res+mod)%mod;
cout<<res<<endl;
}
return 0;
}


 

Problem 1542 - F - Countries
Time Limit: 1000MS   Memory Limit: 65536KB   

Total Submit: 325  Accepted: 52  Special Judge: No
Description

 There are n countries at planet X on which Xiao Ming was born.

 

Some countries, which have been sharing fine bilateral relations, form a coalition and thus all of their citizens will benefit from a policy for which all the travels between these countries will become totally free.

 

But it is not easy to travel between countries distributed in different coalitions. If possible, it must cost some money called YZB(yu zhou bi) which is always positive.

 

Help Xiao Ming determine the minimum cost between countries.

Input

The input consists of one or more test cases.

First line of each test case consists two integers n and m. (1<=n<=10^5, 1<=m<=10^5)

Each of the following m lines contains: x y c, and c indicating the YZB traveling from x to y or from y to x. If it equals to zero, that means x and y are in the same coalition. (1<=x, y<=n, 0<=c<=10^9)

You can assume that there are no more than one road between two countries.

Then the next line contains an integer q, the number of queries.(1<=q<=200)

Each of the following q lines contains: x y. (1<=x, y<=n)

It is guaranteed that there are no more 200 coalitions.

Input is terminated by a value of zero (0) for n.

Output

For each test case, output each query in a line. If it is impossible, output “-1”.

Sample Input

6 5

1 2 0

2 4 1

3 5 0

1 4 1

1 6 2

3

4 2

1 3

4 6

0

Sample Output

1

-1

3

Hint

Source

 

题目大意:题目说有n最大为10^5个点,问你两点之间的最短距离,不过如果两点之间距离为0,那么他们就是

一个国家,最多有200个国家。

 

解题思路:题目到这里就很清楚了,先使用并查集,然后在离散把所有的点一一对应到mp里面去,mp里面最

多有200个点,然后再重新建立边,然后使用floyd,就ok了。

 

题目地址:http://acm.whu.edu.cn/land/problem/detail?problem_id=1545

 

AC代码:

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = 100005;
const int INF = 1e9+7;

int mp[maxn];  //映射表
int fa[maxn];
int dis[205][205];
int u[maxn],v[maxn],w[maxn];

void init()
{
int i,j;
for(i=1;i<maxn;i++)
fa[i]=i;
for(i=1;i<205;i++)
{
for(j=1;j<205;j++)
{
if(i==j) dis[i][j]=0;
else dis[i][j]=INF;
}
}
}

int find1(int x)  //路径压缩的find1
{
if(fa[x]!=x)  fa[x]=find1(fa[x]);
return fa[x];
}

void merge1(int x,int y)
{
x=find1(x);
y=find1(y);
fa[x]=y;
}

void floyd(int n)
{
int i,j,k;
for(k=1;k<n;k++)
{
for(i=1;i<n;i++)
{
for(j=1;j<n;j++)
{
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
}

int main()
{
int n,m,q;
int i;
while(scanf("%d",&n)&&n)
{
scanf("%d",&m);
init();

for(i=1;i<=m;i++)
{
scanf("%d%d%d",&u[i],&v[i],&w[i]);
if(w[i]==0) merge1(u[i],v[i]);
}

int t=1;
for(i=1; i<=n; i++)   //统一标号,离散
if(fa[i] == i)
{
mp[i] = t++;
}

for(i=1; i<=n; i++)
{
if(fa[i]!=i)
{
int tmp=find1(i);
mp[i]=mp[tmp];   //一一映射到标号
}
}

//cout<<mp[1]<<" "<<mp[2]<<" "<<mp[4]<<endl;

//重新建图,给边赋值
for(i=1;i<=m;i++)
{
int x,y;
x=find1(u[i]),y=find1(v[i]);
if(x!=y)
{
x=mp[x],y=mp[y];
dis[x][y]=min(dis[x][y],w[i]);
dis[y][x]=dis[x][y];
}
}

floyd(t);
scanf("%d",&q);
while(q--)
{
int x,y;
scanf("%d%d",&x,&y);
x=mp[x],y=mp[y];

//cout<<x<<" "<<y<<endl;
if(dis[x][y]==maxn) puts("-1");
else printf("%d\n",dis[x][y]);
}
}
return 0;
}


 

Problem 1545 - I - Twenty-four
Time Limit: 1000MS   Memory Limit: 65536KB   

Total Submit: 502  Accepted: 109  Special Judge: No
Description
There are 8 cards :1 1 2 2 3 3 4 4, you need to find out how many ways are there to choose 4 cards and these 4 cards can be used to play the game twenty-four. Attention, there is no difference between cards with the same number, 1 2 2 3 and 1’ 2 2 3 will be regarded as one solution, etc.
 
Hint: twenty-four is a game in which you are given 4 cards marked with numbers, and you may use +, -, * to connect all the four cards and make the result to be 24.
Input
No input in this problem.
Output
Output the result in one line. 
Sample Input
Sample Output
It’s what you need to output. :)
Hint
Source
 

题目大意:题目说的意思是使用+,-,*使得从1,1,2,2,3,3,4,4这八个数里面选四个数使得答案为24的8选4

的方案数,当时我把题目理解错了,觉得使用这个就不能使用括号。题目理解错全错。。。实际上直接组合就好。要不是

YYD,估计后面几个小时我全在写这个题目了。。

有人直接从1开始枚举着往上交。

 

解题思路:直接dfs把。。

 

题目地址:http://acm.whu.edu.cn/land/problem/detail?problem_id=1545

 

AC代码:  ---代码有点搓。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

int a[8]={1,1,2,2,3,3,4,4};
int visi[8];
int b[2005];   //把8个数的排列全部枚举出来压缩保存到b中
int c[4];
int d[4];
int t;
int mp[5005];  //可以的状态按大小排序只要一个

void dfs1(int x)
{
if(x>1000)
{
b[t++]=x;
return;
}
for(int i=0;i<8;i++)
{
if(!visi[i])
{
visi[i]=1;
dfs1(x*10+a[i]);
visi[i]=0;
}
}
}

void dfs2(int cur,int ste)
{
if(ste==4&&cur==24)
{
for(int i=0;i<4;i++)
d[i]=c[i];
sort(d,d+4);
int tmp=0;
for(int i=0;i<4;i++)
tmp=tmp*10+d[i];
mp[tmp]=1;
return;
}
else if(ste==4) return;
dfs2(cur+c[ste],ste+1);
dfs2(cur-c[ste],ste+1);
dfs2(cur*c[ste],ste+1);
}

int main()
{
int i,j;
t=0;
memset(visi,0,sizeof(visi));
memset(mp,0,sizeof(mp));
dfs1(0);

for(i=0;i<t;i++)
{
int tmp=b[i];
for(j=0;j<4;j++)
{
c[j]=tmp%10;
tmp/=10;
}
dfs2(c[0],1);
}

int ans=0;
for(i=0;i<5000;i++)
{
if(mp[i])
ans++;
}
cout<<ans<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: