第一次讨论
首先声明一下:我写的程序比较难看懂,有时候写得长了如果回过去看,我自己也看不懂,而且在说明题意和方法上有些地方可能说的不是很清楚,自己的表达能力比较差,也请多多见谅。
第一题1058 Currency Exchange
这个题目就是一开始就给出五个国家的之间的汇率,然后题目中给一个旅游路线和开始旅游前的钱数,然后问题是计算出经旅游后手中还有多少钱。
这个问题我就模拟了一下,比较苯的办法,没什么算法可言。
具体代码如下:
#include "stdafx.h"
#include "stdio.h"
int main(int argc, char* argv[])
{
int num,n,trip[10],last_city,curr_city,temp_m,i,j;
double rate[5][5],m;
scanf("%d",&num);
while(num>0)
{
for(i=0;i<5;i++)
for(j=0;j<5;j++)
scanf("%lf",&rate[i][j]);
while(1)
{
scanf("%d",&n);
if(n==0)
break;
for(i=0;i<n;i++)
scanf("%d",&trip[i]);
scanf("%lf",&m);
last_city=0;
for(i=0;i<n;i++)
{
curr_city=trip[i]-1;
m=rate[last_city][curr_city]*m;
m=m*100;
temp_m=int(m);
if((m-temp_m)>=0.5)
m=temp_m+1;
else
m=temp_m;
m=m/100;
last_city=curr_city;
}
curr_city=0;
m=rate[last_city][curr_city]*m;
m=m*100;
temp_m=int(m);
if(m-temp_m>=0.5)
m=temp_m+1;
else
m=temp_m;
m=m/100;
printf("%.2f/n",m);
}
if(num!=1)
printf("/n");
num--;
}
return 0;
}
第二题1024 Calendar Game
题目我没做,是一个博弈题目,大概题意是由两个人在玩日历游戏,每个人轮流走,可以选者走下一天,也可以走到下一个月的这一天,比如当前你在2002年1月2日,你可以走到1999年1月3日或者1999年2月2日,但是如果下一个月没有这天的话你只能走下一天,比如1999年1月30日,但是下个月没有30号,所以你唯一的选择是走到1999年1月31日。谁先走到 2001年11月4日后面谁就输了。有两个人比赛Adam和Eve,Adam先走,看Adam有没有策略可以赢。有的话输出YES,否则输出NO。以下思路是学姐提供的,用一个一维的数组存储每一天Adam有没有赢得策略,有的话存1,没的话存0,刚开始从2001年11月3日开始存1,后面的话是根据前一天或前一个月的状态来决定这天的状态,依次类推。比如2000年3月2日可以根据2000年3月3日或2000年4月2日决定,只要有一个为0,2000年3月2日这一天才可以设为1。具体程序没实现过,想想应该可以的。
第三题1161 Gone Fishing
题目是叫我们求出在规定的时间内最多可以钓到的鱼的条数。题目给了我们可用的时间h,湖的个数n,每个湖初始鱼的条f,每在一个湖里钓五分钟之后鱼的数目的减少量d,从前一个湖到后一个湖需要花费的时间t,湖与胡之间的路是单项的,就是一旦走到后面一个湖上去了就不能回来。这道题可以用贪性算法做。钓鱼的湖从第一个湖,前两个湖,前三个一直往后推,然后比较哪个方案钓的鱼比较多。每次都是先把湖与湖之间的耗费时间先剪掉,然后挑那个鱼最多的湖钓,更新湖里鱼的条数,再在有最多鱼的湖里钓,依次类推,直到时间花完。
具体代码如下:
#include "stdafx.h"
#include "iostream.h"
int main(int argc, char* argv[])
{
int n,h,k,fi[25],di[25],ti[25],first,i,j,temp_fi[25],max_fi,max,temp_max,need_h,temp_h,temp_time[25],time[25];
first=0;
while((cin>>n)&&(n!=0))
{
if(first==0)
first=1;
else
cout<<endl;
cin>>h;
for(i=0;i<n;i++)
cin>>fi[i];
for(i=0;i<n;i++)
cin>>di[i];
for(i=1;i<n;i++)
cin>>ti[i];
ti[0]=0;
h=h*12;
max=-1;
temp_max=0;
max_fi=-1;
need_h=0;
for(i=0;i<n;i++)
temp_time[i]=0;
for(i=0;i<n;i++)
{
temp_h=h;
temp_max=0;
for(j=0;j<=i;j++)
{
temp_fi[j]=fi[j];
temp_time[j]=0;
}
need_h=need_h+ti[i];
temp_h=h-need_h;
if(temp_h<=0)
break;
while(temp_h>0)
{
max_fi=-1;
for(j=0;j<=i;j++)
{
if(max_fi<temp_fi[j])
{
max_fi=temp_fi[j];
k=j;
}
}
if(temp_fi[k]<=di[k])
temp_fi[k]=0;
else
temp_fi[k]=temp_fi[k]-di[k];
temp_max=temp_max+max_fi;
temp_time[k]++;
temp_h--;
}
if(temp_max>max)
{
max=temp_max;
for(j=0;j<n;j++)
time[j]=temp_time[j];
}
}
for(j=0;j<n;j++)
{
cout<<time[j]*5;
if(j!=n-1)
cout<<", ";
}
cout<<endl;
cout<<"Number of fish expected: "<<max<<endl;
}
return 0;
}
第四题 1303 Jury Compromise
题目讲的是有一个国家在审案子的时候都要组建一个陪审团,陪审团的成员是从候选的人群中选出来的。这些候选的人每个人都有两个值,分别代表被告和原告给他们的值,从0-20,0代表对此人很厌恶,20表示对此人非常满意。我们的任务是要从这些人中选出一些人满足最佳要求。D(J)=∑d(i) 1=<i<=m, P(J)=∑p(i) 1=<i<=m,m是陪审团的人数。最佳要求就是|D(J)-P(J)|最小,当有两组选择,他们的|D(J)-P(J)|一样,那么选那组使|D(J)+P(J)|最大的。
本题用动态规划做。我也是看了别人的思路才知道怎么做的,但是还没提交成功,路径的存储还没解决。大概思路是这样的:
枚举出所有的得分差,然后求最高得分和。由于m是从0~20,D(J)-P(J)的差值是从-20~20的,所以得分差从-400~400,有801种可能,可以开一个三维数组cost[201][21][801],cost[i][j][k] 表示从前i个人中选j个人时得分差为k的最高得分和。
递推公式是cost[i][j][k]=max(cost[i-1][j][k],cost[i-1][j-1][k-diff[i]]+sum[i]) diff[i],sum[i]是第i个人的差值和和值。等表全部填完后,检察cost[n][m][k],如果cost[n][m][k]存在,选k值最小的就是答案了。
第二次讨论
第一题1076 Gene Assembly
题目的意思是给你一组核苷酸,每一个都有开始和结束,我们的问题是从这些核苷酸中找出能组成的最长的链,要求在链中前一个核苷酸的结束要比后一个核苷酸的开始要早。这题是用贪心算法。先根据结束时间排序,结束时间早的排在前面。然后选择第一个核苷酸,再在剩下的里面找到与这个核苷酸兼容的第一个核苷酸,找完后,再在剩下的里面找与第二个兼容的第一个核苷酸,依次类推,直到没有核苷酸可找,就停止。
具体代码如下:
#include "stdafx.h"
#include "iostream.h"
int main(int argc, char* argv[])
{
int n,start[1001],i,j,end[1001],num[1001],temp_start,temp_end,temp_num,number,path[1001],last_num;
while((cin>>n)&&(n!=0))
{
for(i=1;i<=n;i++)
{
cin>>start[i]>>end[i];
num[i]=i;
}
for(i=2;i<=n;i++)
{
temp_start=start[i];
temp_end=end[i];
temp_num=num[i];
for(j=i-1;j>=1;j--)
{
if(temp_end<end[j])
{
start[j+1]=start[j];
end[j+1]=end[j];
num[j+1]=num[j];
}
else
break;
}
start[j+1]=temp_start;
end[j+1]=temp_end;
num[j+1]=temp_num;
}
number=1;
path[1]=num[1];
last_num=1;
j=2;
i=2;
while(i<=n)
{
if(start[i]>end[last_num])
{
path[j++]=num[i];
last_num=i;
i++;
number++;
}
else
i++;
}
//cout<<number<<' ';
for(i=1;i<number;i++)
cout<<path[i]<<' ';
cout<<path[i]<<endl;
}
return 0;
}
第二题1203 Swordfish
题目是给我们一组城市的二维坐标,计算一条路径能把所有的城市连起来的但总的距离最小的通路。就是最小生成树问题。
具体代码如下:
#include "stdafx.h"
#include "stdio.h"
#include "math.h"
int main(int argc, char* argv[])
{
int n,i,j,k,temp,know[101],number,flag;
double postion[101][2],dis[101][101],distance,min,cost;
number=1;
flag=1;
while((scanf("%d",&n))&&(n!=0))
{
if(flag==1)
flag=2;
else
printf("/n");
for(i=1;i<=n;i++)
scanf("%lf %lf",&postion[i][0],&postion[i][1]);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
if(i==j)
dis[i][j]=1000000000;
else
{
distance=(postion[i][0]-postion[j][0])*(postion[i][0]-postion[j][0])+(postion[i][1]-postion[j][1])*(postion[i][1]-postion[j][1]);
dis[i][j]=sqrt(distance);
}
}
for(i=1;i<=n;i++)
know[i]=0;
know[1]=1;
cost=0;
for(i=2;i<=n;i++)
{
min=100000000;
for(j=1;j<=n;j++)
{
if(know[j]==1)
{
for(k=1;k<=n;k++)
if((dis[j][k]<min)&&(know[k]==0))
{
min=dis[j][k];
temp=k;
}
}
}
if(min!=100000000)
{
cost=cost+min;
know[temp]=1;
}
}
printf("Case #%d:/n",number);
printf("The minimal distance is: %.2f/n",cost);
number++;
}
return 0;
}
第三题1082 Stockbroker Grapevine
这道题目是最短路径,求城市到别的城市的最短路径。可以用最短路径算法解决。
本文解析了四道经典的编程题目,包括货币兑换、日历游戏、钓鱼问题和陪审团妥协,涵盖了模拟、贪心算法、动态规划等多种解题思路。
302

被折叠的 条评论
为什么被折叠?



