题1 神奇的风
【问题描述】
T博士最近在研究一种神奇的风。这种风有一个源头,称之为“风口”。风口的风要么是顺时针的,要么是逆时针的。这种风是有能量的。这种风是能传播的,如果风口周围都能传播风,风会像这样产生下一级的风:(箭头表示风的转向,最中间的是风口,图中风口的风是顺时针的,对于风口的风是逆时针的情形可通过物理模型想象一下或由这个图推理。)产生的下一级风的能量依据新产生的风所在的地形决定,有两种可以传递这种风的地形:一、平地,下一级风的能量与风口的风能量相等..,这种地形用“.”表示。二、少量障碍物,下一级风的能量是风口的风能量的一半..,这种地形用“*”表示。每个新产生的风都能作为新的风口继续产生下一级风。此外,还有一种地形是不能传递风的:大量障碍物,用“#”表示。如果在风口的某一方向是“#”地形,则该方向不会产生下一级风,其他方向视该位置........的地形而定,就是说,如果是“................”或“...*.”地形则该方向照样传播...........。T博士还发现了这种神奇的风的叠加规则:两股风叠加时,无论它们的转向是否相同,都只保留能量较大的那股风...........,即风叠加后的能量和转向都与叠加前能量较大的那股风相同。而如果叠加的两股风的能量相同且转向相同,则保留其中任意一股。两股风能量相同且转向不同时叠加的情况未知,因为T博士至今还没碰到这样的情况。T博士画了几张地图,他想知道地图上的某点风的转向和能量。
【输入格式】
输入文件wind.in的第一行是两个整数m和n,表示地图大小为m行n列。接下来的m行,每行是n个字符,只会是以下的几种:“S”表示风口,保证图中有且仅有一个“S”。“E”表示目的地,即T博士想知道的那个点。“.”“*”“#”见描述。第m+2行是一个整数“0”或“1”,分别表示风口的风是顺时针方向或逆时针方向。约定“S”处的风能量为16384,“S”和“E”处的地形均为平地。
【输出格式】
输出文件为wind.out。第 1 页 共 5 页Noip2010若目的地会有风传到,则输出两行:第一行为一个整数,为目的地的风的能量;第二行为一个整数“0”或“1”,表示意义同输入格式。此种情形下保证目的地的风的能量大于0。若目的地没有风传到,则输出一行:“There’s no wind!”(双引号内的字符,全英文标点)。
【样例输入1】
3 4
####
S**E
####
0
【样例输出1】
4096
(传递过程中经过两个“*”地形,能量变为原来的1/4,即变为4096)1 (E处的风是逆时针的)
【样例输入2】
2 4
....
S**E
0
【样例输出2】
16384
(传到目的地的风能量最大的为16384)1(E处的风是逆时针的)
【样例输入3】
6 8
********
********
***S****
###*....
...#....
E..#....
1
【样例输出3】
There’s no wind!
【数据范围】
对于20%的数据,m,n均不超过10。对于50%的数据,m,n均不超过100。对于100%的数据,m,n均不超过200。
【提示】不要问我单引号怎么输出。
#include<fstream> #include<cstring> using namespace std; ifstream cin("wind.in"); ofstream cout("wind.out"); int n,m; char c; int a[210][210],sum[210][210],d[210][210]; int sti,stj,eni,enj; bool v[210][210]; struct node { int energy,dir,x,y; }f[1000000]; int main() { int i,j; cin>>n>>m; memset(a,63,sizeof(a)); for (i=1;i<=n;i++) for (j=1;j<=m;j++) { cin>>c; if (c=='#') a[i][j]=2; else if (c=='*') a[i][j]=1; else if (c=='.') a[i][j]=0; else if (c=='S') {sti=i;stj=j;a[i][j]=0;} else if (c=='E') {eni=i;enj=j;a[i][j]=0;} } int head=0,tail=1; cin>>f[1].dir; f[1].energy=16384; f[1].x=sti; f[1].y=stj; while (head<tail) { head++; int x=f[head].x,y=f[head].y; if ((x-1)>0) { if (a[x-1][y]==0) if (sum[x-1][y]<f[head].energy) { sum[x-1][y]=f[head].energy; d[x-1][y]=1-f[head].dir; tail++; f[tail].x=x-1; f[tail].y=y; f[tail].energy=sum[x-1][y]; f[tail].dir=1-f[head].dir; } if (a[x-1][y]==1) if (sum[x-1][y]<(f[head].energy/2)) { sum[x-1][y]=(f[head].energy>>1); d[x-1][y]=1-f[head].dir; tail++; f[tail].x=x-1; f[tail].y=y; f[tail].energy=sum[x-1][y]; f[tail].dir=1-f[head].dir; } } if ((y-1)>0) { if (a[x][y-1]==0) if (sum[x][y-1]<f[head].energy) { sum[x][y-1]=f[head].energy; d[x][y-1]=1-f[head].dir; tail++; f[tail].x=x; f[tail].y=y-1; f[tail].energy=sum[x][y-1]; f[tail].dir=1-f[head].dir; } if (a[x][y-1]==1) if (sum[x][y-1]<(f[head].energy/2)) { sum[x][y-1]=(f[head].energy>>1); d[x][y-1]=1-f[head].dir; tail++; f[tail].x=x; f[tail].y=y-1; f[tail].energy=sum[x][y-1]; f[tail].dir=1-f[head].dir; } } if ((x+1)<=n) { if (a[x+1][y]==0) if (sum[x+1][y]<f[head].energy) { sum[x+1][y]=f[head].energy; d[x+1][y]=1-f[head].dir; tail++; f[tail].x=x+1; f[tail].y=y; f[tail].energy=sum[x+1][y]; f[tail].dir=1-f[head].dir; } if (a[x+1][y]==1) if (sum[x+1][y]<(f[head].energy/2)) { sum[x+1][y]=(f[head].energy>>1); d[x+1][y]=1-f[head].dir; tail++; f[tail].x=x+1; f[tail].y=y; f[tail].energy=sum[x+1][y]; f[tail].dir=1-f[head].dir; } } if ((y+1)<=m) { if (a[x][y+1]==0) if (sum[x][y+1]<f[head].energy) { sum[x][y+1]=f[head].energy; d[x][y+1]=1-f[head].dir; tail++; f[tail].x=x; f[tail].y=y+1; f[tail].energy=sum[x][y+1]; f[tail].dir=1-f[head].dir; } if (a[x][y+1]==1) if (sum[x][y+1]<(f[head].energy/2)) { sum[x][y+1]=(f[head].energy>>1); d[x][y+1]=1-f[head].dir; tail++; f[tail].x=x; f[tail].y=y+1; f[tail].energy=sum[x][y+1]; f[tail].dir=1-f[head].dir; } } } if (sum[eni][enj]>0) {cout<<sum[eni][enj]<<endl;cout<<d[eni][enj]<<endl;}else cout<<"There's no wind!"<<endl; return 0; }
【问题描述】众所周知,HYF有很多小姊妹。HYF每天放学之后都要跟(不同的)MM约会。HYF这天约会的时候不巧被jzt撞上了……虽然换一个新的MM约会这种事情对于HYF来说如同家常便饭,所谓“好事不出门,坏事传千里”,jzt迅速将这个消息传播开来。每个听到这个消息的人首先会震惊一段时间(他怎么又换MM了- -~!),但是这样的震惊只会持续2个时刻(因为这对于HYF来说太正常了= =~!)。如果他在第i个时刻听到这个消息,就会从第(i+2)个时刻开始传播这个消息,每个时刻把这个消息告诉两个人,当然他只会告诉不知道这个消息的人。但是当他连续告诉了10个人之后,他就会口干舌燥,停止传播。jzt在第0时刻撞到HYF(当然jzt也有震惊时间),请问第N时刻共有多少人知道了这个消息?
【输入格式】一行一个整数N,表示第N时刻。
【输出格式】一行一个整数,表示N分钟后知道这个消息的总人数。
【输入样例1】
4
【输出样例1】
11
【样例解释】
时刻0:一开始只有jzt知道时刻2:jzt开始传播,时刻2传播给A和B,时刻3传播给C和D,时刻4传播给E和F;时刻4:A和B在4开始传播,时刻4传播给2×2=4个人,传播给H、I、J、K;最后知道消息的共有:jzt,A,B,C,D,E,F,H,I,J,K,共11个人。
【输入样例2】
1
【输出样例2】
1
【输入样例3】
10
【输出样例3】
651
【数据规模】
20%的数据,N<=2060%的数据,N<=1000100%的数据,N<=10000
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
type arr=array[0..500]of longint;
var f:array[0..10000]of arr;
i,j,n,t:longint;
ans:arr;
function plus(a,b:arr):arr;
var i:longint;
begin
if a[0]<b[0] then a[0]:=b[0];
a[0]:=a[0]+2;
for i:=1 to a[0] do
begin
inc(a[i],b[i]);
inc(a[i+1],a[i] div 100000000);
a[i]:=a[i] mod 100000000;
end;
while (a[a[0]]=0)and(a[0]>1) do dec(a[0]);
exit(a);
end;
begin
assign(input,'spread.in');reset(input);
assign(output,'spread.out');rewrite(output);
readln(n);
for i:=0 to n do
begin
f[i][0]:=1;
f[i][1]:=1;
end;
for i:=2 to n do
begin
t:=i-2;
for j:=1 to 5 do
if t>=0 then
begin
f[i]:=plus(f[i],f[t]);
f[i]:=plus(f[i],f[t]);
dec(t);
end
else break;
end;
ans:=f[n];
write(ans[ans[0]]);
for i:=ans[0]-1 downto 1 do
begin
if ans[i] div 10000000=0 then write(0);
if ans[i] div 1000000=0 then write(0);
if ans[i] div 100000=0 then write(0);
if ans[i] div 10000=0 then write(0);
if ans[i] div 1000=0 then write(0);
if ans[i] div 100=0 then write(0);
if ans[i] div 10=0 then write(0);
write(ans[i]);
end;
writeln;
close(input);close(output);
end.
题3 窈窕淑女
T博士的大儿子阿T(阿嚏?)最近遇到了一件麻烦事。有n个MM同时邀请阿T在8月14日上午11:30拜访她们家,可那时阿T刚比赛完,所以不能先提前拜访几个,而他又不会分身术,所以他只得分别拜访。他共有T分钟的时间可以用于拜访MM。他还安排好了拜访的顺序,对于每个MM都可以选择拜访或不拜访..........。对于要.拜访的...MM..必须按阿....T.安排好的顺序拜访........。对于每个MM都有如下数据:不高兴系数x,为2到9的整数。不高兴度X,若阿T迟到t分钟到她家,则X=x^t(x的t次方);若阿T不拜访她家,则X=x^T。拜访时间y(分钟),保证0<yi<=T,即阿T在她家停留的时间,若阿..T.在到了她家.....但.停留时间不足......y.分钟,她的不高兴度就会变成正无穷大.................。假设阿T从一个地方到另一个地方不用消耗时间,阿T希望在有限的T分钟里使所有MM的不高兴度之和最小。请告诉他这个最小值是多少。
【输入格式】
输入文件girls.in的第一行是两个正整数n和T。第1+i(1<=i<=n)有两个正整数xi和yi,分别是阿T安排的拜访顺序中第i个MM的不高兴系数和拜访时间。
【输出格式】
输出文件是girls.out。请只输出一行,仅一个正整数,为最小的不高兴度之和。
【样例输入1】2 1005 302 70
【样例输出1】1073741825 (两个MM都拜访,到第一个MM家时迟到了0分钟,到第二个MM家时迟到了30分钟,所以不高兴度之和为5^0+2^30)
【样例输入2】2 305 162 16
【样例输出2】1073741825 (只拜访第一个MM,到她家时迟到了0分钟,不高兴度之和为5^0+2^30;若只拜访第二个MM,则不高兴度之和为2^0+5^30,显然较大)
【数据范围】对于20%的数据,满足1<=n<=10,1<=T<=9;对于50%的数据,满足1<=n<=20,1<=T<=30;对于100%的数据,满足1<=n<=20,1<=T<=180;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
type arr=array[0..1000]of longint;
var i,j,k,m,n:longint;
f:array[0..180]of arr;
x,y:array[0..180]of longint;
a,b:arr;
function plus(a,b:arr):arr;
var c:arr;
i,j,len,g:longint;
begin
fillchar(c,sizeof(c),0);
if a[0]>b[0] then len:=a[0]+1 else len:=b[0]+4;
g:=0;
for i:=1 to len do
begin
c[i]:=a[i]+b[i]+g;
g:=c[i] div 10;
c[i]:=c[i] mod 10;
end;
while (c[len]=0)and(len>1) do dec(len);
c[0]:=len;
exit(c);
end;
function power(a,p:longint):arr;
var c:arr;
i,j,x:longint;
begin
fillchar(c,sizeof(c),0);
if a=0 then exit(c);
c[0]:=1;c[1]:=1;
for i:=1 to p do
begin
x:=0;
for j:=1 to c[0] do
begin
x:=x+c[j]*a;
c[j]:=x mod 10;
x:=x div 10;
end;
while x<>0 do
begin
inc(c[0]);
c[c[0]]:=x mod 10;
x:=x div 10;
end;
end;
exit(c);
end;
function min(a,b:arr):arr;
var i:longint;
begin
if a[0]<0 then exit(b) else if b[0]<0 then exit(a);
if a[0]<b[0] then exit(a) else if a[0]>b[0] then exit(b);
for i:=a[0] downto 1 do
if a[i]>b[i] then exit(b) else if a[i]<b[i] then exit(a);
exit(a);
end;
begin
assign(input,'girls.in');reset(input);
assign(output,'girls.out');rewrite(output);
readln(n,m);
for i:=1 to n do readln(x[i],y[i]);
f[0][0]:=0;
for i:=1 to m do f[i][0]:=-1;
for i:=1 to n do
for j:=m downto 0 do
begin
if f[j][0]>=0 then
f[j]:=plus(f[j],power(x[i],m));
if (j-y[i]>=0)and(f[j-y[i]][0]>=0) then
begin
b:=plus(f[j-y[i]],power(x[i],j-y[i]));
f[j]:=min(f[j],b);
end;
end;
a[0]:=-1;
for i:=m downto 0 do a:=min(f[i],a);
for i:=a[0] downto 1 do write(a[i]);
close(input);close(output);
end.
题4 新版方格取数
【问题描述】
T博士的小儿子小T最近在玩一个游戏。在一个m行n列的方格中有m*n个数,游戏规则如下:先在方格边缘取走一个数,以此格为起点,下一步可向该格四个方向中未取数...的方格前进,取走该方格的数并继续按如上规则取数。如果某次取数恰好取到方格的边缘,则下一步可选择离开方格另取入口进入方格,当然也可以选择按上述规则取数。游戏在小T取完方格内所有数或无法继续取方格内剩下的任何一个数的时候结束。游戏有这样的得分规则:若方格内的某数j是方格内所有数中第........i.个取走的数.....,此次取数的得分为i*j。小T最后的得分为游戏结束时他各次取数的得分之和。小T想知道他所能取得的最大得分。注意:已经取走数的方格不能再次取数或经过.................。
【输入格式】
输入文件newfgqs.in的第一行是两个正整数m和n,表示方格为m行n列。第2到m+1行,每行为n个非负整数(注意可能为.....0.),是方格里的数,保证这些数都小于100000(10万)。
【输出格式】
输出文件为newfgqs.out。只要输出一行,为小T能取得的最大得分。
【样例输入1】
3 3
1 2 3
8 9 4
7 6 5
【样例输出1】
285 (依次取1,2,3,4,5,6,7,8,9)
【样例输入2】
3 3
0 0 0
0 1 0
0 0 0
【样例输出2】
9 (周围绕一圈,第9次取1)
【数据范围】对于50%的数据,满足m*n<=9。对于100%的数据,满足m*n<=16。
...还不会...