C. 袋鼠妈妈找孩子
Time limit per test: 1.5 seconds
Memory limit: 256 megabytes
Accept / Submit: 41 / 172
袋鼠妈妈找不到她的孩子了。她的孩子被怪兽抓走了。
袋鼠妈妈现在在地图的左上角,她的孩子在地图第 x 行第 y 列的位置。怪兽想和袋鼠妈妈玩一个游戏:他不想让袋鼠妈妈过快地找到她的孩子。袋鼠妈妈每秒钟可以向上下左右四个方向跳一格(如果没有墙阻拦的话),怪兽就要在一些格子中造墙,从而完成一个迷宫,使得袋鼠妈妈能够找到她的孩子,但最快不能小于 k 秒。
请设计这样一个迷宫。
Input
第一行两个整数 n,m (1≤n,m≤8) ,表示地图的总行数和总列数。
第二行三个整数 x,y,k (1≤x≤n,1≤y≤m,x+y>1) 。
Output
输出一个地图,应正好 n 行 m 列。
用 .
表示空地,用 *
表示墙。袋鼠妈妈所在的位置和孩子所在的位置用 .
表示。
数据保证有解。
Examples
2 6 1 3 4
.*.*** ......
题目链接:http://acm.ecnu.edu.cn/problem/3260/
AC代码:
/**
* 行有余力,则来刷题!
* 博客链接:http://blog.csdn.net/hurmishine
*
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn=10;
char a[maxn][maxn];
int dir[4][2]= {1,0,0,1,-1,0,0,-1};
int n,m;
int ex,ey,T;
bool DFS(int x,int y,int t)//当前位置,所用时间
{
if(x==1&&y==1)
return t>=T;
for(int i=0; i<4; i++)
{
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(!xx||!yy||xx>n||yy>m||a[xx][yy]!='*')
continue;
int cnt=0;
//(xx,yy)这个点只能由(x,y)到达
for(int j=0;j<4;j++)
{
int u=xx+dir[j][0];
int v=yy+dir[j][1];
if(a[u][v]=='.')
cnt++;
}
if(cnt>1)
continue;
a[xx][yy]='.';
if(DFS(xx,yy,t+1))
return true;
a[xx][yy]='*';
}
return false;
}
int main()
{
//freopen("C:\\Documents and Settings\\Administrator\\桌面\\data.txt","r",stdin);
while(cin>>n>>m)
{
cin>>ex>>ey>>T;
memset(a,'*',sizeof(a));
for(int i=0;i<=n;i++)
{
for(int j=0;j<=m;j++)
a[i][j]='*';
}
a[ex][ey]='.';
DFS(ex,ey,0);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
cout<<a[i][j];
cout<<endl;
}
}
return 0;
}
E. 黑心啤酒厂
Time limit per test: 1.0 seconds
Memory limit: 256 megabytes
Accept / Submit: 1184 / 4093
黑心啤酒厂为了让大家买啤酒,会把一瓶酒设计成恰好能倒七杯。由于聚会时经常会有大家一起干杯这样的事情,干杯之前又要给每个人都倒满,所以来两个人的时候,干完三轮,恰好多一杯;三个人的时候,干完两轮,恰好多一杯;四个人的时候会多三杯。在上述情况下,为了践行不浪费的原则,就会多买一瓶啤酒,再干一轮。当然多买的啤酒可能又有多了……然后循环往复,喝了好多好多。直到啤酒刚刚好喝完为止。
现在啤酒厂把酒瓶设计成刚好能倒 x 杯,请依次求出有 2 人、 3 人,一直到 n 人参加聚会时,啤酒厂各能卖出多少瓶啤酒。
Input
输入只有一行,两个整数 x,n (1≤x≤109,2≤n≤105) 。
Output
输出 n−1 行,分别表示 2,3,…,n 人参加聚会时,能卖出的啤酒瓶数。
Examples
7 5
2 3 4 5
暴力枚举肯定超时,简单用数学知识推一下就可以了.
假设需要k瓶,则
kx%n=0
-->gcd=GCD(x,n)
-->k=x/gcd*n/x
计算
x
与n的最小公倍数,就是这些人至少需要喝几杯,最小公倍数除以
i
x
x就是要买几瓶。
AC代码:
**
* 行有余力,则来刷题!
* 博客链接:http://blog.csdn.net/hurmishine
*
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=0;
typedef long long LL;
LL GCD(LL x,LL y)
{
if(y==0)
return x;
return GCD(y,x%y);
}
int main()
{
//freopen("C:\\Documents and Settings\\Administrator\\桌面\\data.txt","r",stdin);
LL x,n;
while(cin>>x>>n)
{
for(LL y=2; y<=n; y++)
{
LL gcd=GCD(x,y);
cout<<x/gcd*y/x<<endl;
}
}
return 0;
}
F. 丽娃河的狼人传说
Time limit per test: 1.0 seconds
Memory limit: 256 megabytes
Accept / Submit: 224 / 1759
丽娃河是华师大著名的风景线。但由于学校财政紧缺,丽娃河边的路灯年久失修,一到晚上就会出现走在河边要打着手电的情况,不仅非常不方便,而且影响安全:已经发生了大大小小的事故多起。
方便起见,丽娃河可以看成是从 1 到 n 的一条数轴。为了美观,路灯只能安装在整数点上,每个整数点只能安装一盏路灯。经专业勘测,有 m 个区间特别容易发生事故,所以至少要安装一定数量的路灯,
请问至少还要安装多少路灯。
Input
第一行一个整数 T (1≤T≤300) ,表示测试数据组数。
对于每组数据:
-
第一行三个整数 n,m,k (1≤n≤103,1≤m≤103,1≤k≤n) 。
-
第二行 k 个不同的整数用空格隔开,表示这些位置一开始就有路灯。
-
接下来 m 行表示约束条件。第 i 行三个整数 li,ri,ti 表示:第 i 个区间 [li,ri] 至少要安装 ti 盏路灯 (1≤li≤ri≤n,1≤ti≤n) 。
Output
对于每组数据,输出 Case x: y
。其中 x 表示测试数据编号(从 1 开始),y 表示至少要安装的路灯数目。如果无解,y 为
−1
。
Examples
3 5 1 3 1 3 5 2 3 2 5 2 3 1 3 5 2 3 2 3 5 3 5 2 3 1 3 5 2 3 2 4 5 1
Case 1: 1 Case 2: 2 Case 3: 1
Note
因为今天不是满月,所以狼人没有出现。
暴力贪心可以过,当然也有更好的方法.
AC代码:
/**
* 行有余力,则来刷题!
* 博客链接:http://blog.csdn.net/hurmishine
*
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e3+5;
int n,m,k;
struct Node
{
int l,r,s;
}a[maxn];
bool vis[maxn];
bool cmp(Node x,Node y)
{
return x.r<y.r;
}
int solve()
{
int ans=0;
for(int i=0;i<m;i++)
{
if(a[i].r-a[i].l+1<a[i].s)
return -1;
int cnt=0;
for(int j=a[i].l;j<=a[i].r;j++)
cnt+=vis[j];
if(cnt>=a[i].s)
continue;
for(int j=a[i].r;j>=a[i].l;j--)
{
if(!vis[j])
{
vis[j]=true;
cnt++;
ans++;
if(cnt==a[i].s)
break;
}
}
}
return ans;
}
int main()
{
//freopen("C:\\Documents and Settings\\Administrator\\桌面\\data.txt","r",stdin);
int T,kase=0;
cin>>T;
while(T--)
{
cin>>n>>m>>k;
int x;
memset(vis,false,sizeof(vis));
for(int i=0;i<k;i++)
{
cin>>x;
vis[x]=true;
}
int l,r,k;
for(int i=0;i<m;i++)
{
cin>>l>>r>>k;
a[i]=Node{l,r,k};
}
sort(a,a+m,cmp);
printf("Case %d: %d\n",++kase,solve());
}
return 0;
}
G. 铁路修复计划
Time limit per test: 2.0 seconds
Memory limit: 256 megabytes
Accept / Submit: 146 / 1219
在 A 国有很多城际铁路。这些铁路都连接两个城市(城市从 1 到 n 编号),可以双向通行,使得任意两个城市之间都由铁路网联系起来。
不过在一次星球大战之后,所有的铁路都经历了不同程度的损伤以至于无法通行了。由于经费紧缺,A 国政府不愿意再出资造新的铁路。对于原有的城际铁路,根据铁路的实际情况,有以下两种处理办法:
- 使用国内技术进行修复:主要针对损坏情况不是很严重的铁路。国内公司会对铁路状况进行评估,然后如实开出铁路修复的费用。
- 使用国外技术进行修复:主要针对损坏情况严重的铁路。国外公司也会对铁路情况进行评估,然后按照铁路实际修复费用的 k 倍来收费(其中 k 是一个由国外公司决定的实数,不管怎么说,优惠是不可能的,所以 k≥1 )。
A国政府修复铁路的总预算是 M ,目标是要让任意两个城市之间都能通过铁路联系起来。在预算不够且能够完成目标的条件下,显然没必要修复每一条铁路。
国外公司通过不知什么途径了解到了 A 国政府的总预算 M ,他们现在要把 k 定下来,并且希望 k 尽可能得大。但 k 又不能太大,不然,如果 A 国政府发现无法完成任务的话,整个订单都会泡汤。
Input
测试数据包含不超过 30 个测试文件。每个测试文件是单个测试点。
第一行是三个整数 n,m,M (2≤n≤105,n−1≤m≤min{105,n(n−1)2},1≤M≤1015) 。
接下来 m 行,每行四个整数 ui,vi,ti,fi 。表示一条城际铁路,连接着 ui 和 vi 城市, ti 表示铁路实际修复费用。 fi=1 表示只能由国外公司修复, fi=0 表示由国内公司修复。 (1≤ui,vi≤n,ui≠vi,1≤ti≤106,fi∈{0,1}) 。输入保证两个城市之间不会存在多条铁路。
输入保证:
- 在国外公司不乱收费 (k=1) 的情况下,使用预算能完成要求。
- 完全不使用国外技术,只使用国内技术,是不能完成目标的。
Output
求 k 的最大值。输出答案与标准答案相差不超过 10−6 即判为正确。
Examples
3 3 9 1 2 1 1 1 3 2 0 2 3 1 1
7.000000
3 3 9 1 2 1 1 1 3 2 1 2 3 2 1
3.000000
二分就可以了,
AC代码:
/**
* 行有余力,则来刷题!
* 博客链接:http://blog.csdn.net/hurmishine
*
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=100005;//1e5+5;
int n,m;
double M,k;
struct Node
{
int u,v,f;
double w;
}a[maxn];
int fa[maxn];
int Find(int x)
{
if(fa[x]==x)
return x;
return fa[x]=Find(fa[x]);
}
bool cmp(Node &a,Node &b)
{
double x,y;
if(a.f)
x=a.w*k;
else
x=a.w;
if(b.f)
y=b.w*k;
else
y=b.w;
return x<y;
}
bool OK()
{
for(int i=0;i<=n;i++)
fa[i]=i;
sort(a+1,a+1+m,cmp);
double sum=0;
int cnt=0;
for(int i=1;i<=m;i++)
{
int fu=Find(a[i].u);
int fv=Find(a[i].v);
if(fu==fv)
continue;
fa[fu]=fv;
if(a[i].f)
sum+=a[i].w*k;
else
sum+=a[i].w;
if(++cnt==n-1)
break;
}
return sum<=M;
}
int main()
{
//freopen("C:\\Documents and Settings\\Administrator\\桌面\\data.txt","r",stdin);
while(cin>>n>>m>>M)
{
double minn=100000000;//1e5;
for(int i=1;i<=m;i++)
{
//cin>>a[i].u>>a[i].v>>a[i].w>>a[i].f;
scanf("%d%d%lf%d",&a[i].u,&a[i].v,&a[i].w,&a[i].f);
if(a[i].f)
minn=min(a[i].w,minn);
}
double l=1,r=M/minn;
while(fabs(r-l)>1e-6)
{
//cout<<l<<","<<r<<endl;
double mid = (l+r)/2;
k=mid;
if(OK())
l=mid;
else
r=mid;
}
printf("%.6f\n",l);
}
return 0;
}
剩下的题,随缘吧.