T1:上海红茶馆 ChineseTea.cpp
问题描述:
你现在正在经营一家红茶馆, 而且这里有各种各样的红茶, 你现在把这些红茶分成了N个等级, 每个等级的茶有一个品质Q。
现在每一个来的客人都会要求一个品质为S的茶, 你需要迅速的回答他是否有。
输入格式:
第一行两个数N,M。
下面一行N个数, 分别表示每个等级的茶的品质Q。
下面一行M个数, 分别表示询问的品质S。
输出格式:
输出一行M个字符, 表示回答是否。 Y表示有, N表示没有。
样例输入:
5 5
1 3 4 6 8
1 2 3 4 5
样例输出:
YNYYN
数据规模:
30%:N,M<5000
100%:N,M<200000
据说c++map一下就解决了~~但由于ywd垃圾的评测机被卡成60~~ 没有map的c选手只好先快排再写个二分查找。附上代码:
`
#include
#include
FILE*fin,*fout;
int a[200050]={0};
int n,m,flag=0;
int binsearch(int left,int right,int goal)
{
int mid;
mid=(left+right)/2;
if(a[mid]==goal)
{
flag=1;
return 0;
}
if(flag==1||left>=right) return 0;
if(a[mid]>goal) {binsearch(left,mid-1,goal);}
else if(a[mid]mid) j--;
if(i<=j)
{
t=a[i];a[i]=a[j];a[j]=t;
i++;j--;
}
}
if(ileft) quicksort(left,j);
return 0;
}
int main()
{
int x,i;
fin=fopen("chinesetea.in","r");
fout=fopen("chinesetea.out","w");
fscanf(fin,"%d%d",&n,&m);
for(i=1;i<=n;i++)
fscanf(fin,"%d",&a[i]);
quicksort(1,n);
for(i=1;i<=m;i++)
{
flag=0;
fscanf(fin,"%d",&x);
binsearch(1,n,x);
if(flag==1)
fprintf(fout,"Y");
else fprintf(fout,"N");
}
fclose(fin);
fclose(fout);
return 0;
}
T2:
软件安装 install.cpp
问题描述:
现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi。我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大)。
但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j)。幸运的是,一个软件最多依赖另外一个软件。如果一个软件不能正常工作,那么它能够发挥的作用为0。
我们现在知道了软件之间的依赖关系:软件i依赖软件Di。现在请你设计出一种方案,安装价值尽量大的软件。一个软件只能被安装一次,如果一个软件没有依赖则Di=0,这时只要这个软件安装了,它就能正常工作。
Input
第1行:N, M (0<=N<=100, 0<=M<=500)
第2行:W1, W2, ... Wi, ..., Wn (0<=Wi<=M )
第3行:V1, V2, ..., Vi, ..., Vn (0<=Vi<=1000 )
第4行:D1, D2, ..., Di, ..., Dn (0<=Di<=N, Di≠i )
Output
一个整数,代表最大价值。
Sample Input
3 10
5 5 6
2 3 4
0 1 1
Sample Output
5
这个题难度对我这种蒟蒻实在太高了,我一开始一看觉得是个背包,想把有依赖条件的物品创造出一个新的物品,推了半天没推出来,然后从网络流的角度想,构一个终极源点和终极汇点在里面跑一个总体积小于m的最大流由于网络流写炸而且这玩意最后听说可能和费用流这种我不会的东西有关。最后强打暴力O(2^n)加一通玄学剪枝40分。正解应是tarjan缩点(防止循环依赖)然后再跑树形dp。附上惨不忍睹的暴力代码:
#include
#include
FILE*fin,*fout;
int v[100001]={0},w[100001]={0},vis[100001]={0},fa[100001]={0},used[100001]={0};
int n,m,ans=-1,vsum=0;
int judge()
{
int i,sum=0;
for(i=1;i<=n;i++)
if(fa[i]==0&&vis[i]==1)
{
sum+=w[i];
}
else if(vis[i]==1)
{
if(used[fa[i]]==1)
{
used[i]=1;
sum+=w[i];
}
}
if(sum>ans) ans=sum;
return 0;
}
int dfs(int i)
{
if(vsum>m)
return 0;
if(i==n+1)
{
judge();
return 0;
}
vis[i]=1;
if(fa[i]==0||used[fa[i]]==1)
used[i]=1;
vsum+=v[i];
if(used[i]==1)
dfs(i+1);
vsum-=v[i];
used[i]=0;
vis[i]=0;
dfs(i+1);
return 0;
}
int main()
{
int i,j;
fin=fopen("install.in","r");
fout=fopen("install.out","w");
fscanf(fin,"%d%d",&n,&m);
for(i=1;i<=n;i++)
fscanf(fin,"%d",&v[i]);
for(i=1;i<=n;i++)
fscanf(fin,"%d",&w[i]);
for(i=1;i<=n;i++)
fscanf(fin,"%d",&fa[i]);
dfs(1);
fprintf(fout,"%d",ans);
fclose(fin);
fclose(fout);
return 0;
}
T3:乘电梯
一道区间dp,我也懒得看了,直接敲暴力,50分。今年noip我肯定会因为dp不擅长吃很多亏。
#include
#include
FILE*fin,*fout;
double time[100001]={0};
int s[100001]={0},t[100001]={0},vis[100001]={0};
double ans=214748361,sum=0;
int n,m;
double cal(double a,double b)
{
return (a*(a+1)+b*(b+1))/(2*(a+b+1));
}
int dfs(int fnum)
{
int i;
if(sum+m-1>ans) return 0;
if(time[fnum]t[i]) break;
if(fnum<=t[i]&&fnum>=s[i]&&vis[i]==0)
{
sum+=cal(t[i]-fnum,fnum-s[i]);
vis[i]=1;
dfs(s[i]);
vis[i]=0;
sum-=cal(t[i]-fnum,fnum-s[i]);
}
}
return 0;
}
int quicksort(int left,int right)
{
int i,j,mid,t1;
i=left;j=right;mid=t[(i+j)/2];
while(i<=j)
{
while(t[i]>mid) i++;
while(t[j]left) quicksort(left,j);
return 0;
}
int main()
{
int i;
fin=fopen("lifts.in","r");
fout=fopen("lifts.out","w");
fscanf(fin,"%d%d",&n,&m);
for(i=1;i<=n;i++)
fscanf(fin,"%d%d",&s[i],&t[i]);
quicksort(1,n);
dfs(m);
fprintf(fout,"%.5lf",ans);
fclose(fin);
fclose(fout);
return 0;
}
T4:
暗夜骑士 NightOfKnights.cpp
问题描述:
你现在负责管理骑士, 也就是负责城堡的守卫工作。
现在告诉你一个N*M的矩阵, 上面有一些位置有骑士, 有一个位置有入侵者, 还有一个位置是城堡的入口。骑士每一个单位时间, 都会扩展一格视野。 假设骑士在x,y, 那么在时间t, 任意格子i,j,只要满足|x-i|+|y-j|<=t, 那么这些格子上的入侵者都是可以发现的。入侵者每一个单位时间最多可以走一步(可以不走, 方向为上下左右中的一个)。
一旦入侵者被发现就会逃走, 如果在城堡入口被发现了, 也会逃走。你只需要回答最多有多少入侵者可能进入。
输入格式:
第一行4个整数, N,M
下面N行M列的整数描述题中的矩阵, 0表示空地, 1表示骑士, 2表示入侵者, 3表示城堡入口。
输出格式:
输出一行一个整数, 表示最多有多少入侵者可能进入。
样例输入:
6 5
0 0 3 0 0
0 2 0 0 0
0 0 2 0 1
0 0 1 0 0
1 0 0 0 0
0 0 0 2 0
样例输出:
2
数据规模:
40%:N,M 不超过 100, 入侵者和骑士都不超过10
100%: 所有数字不超过1000, 包括骑士数量, 入侵者数量。
这道题名字没有翻成黑暗骑士真是很遗憾了。我用了一个贪心的想法,假如你一个入侵者到城堡的距离>=离城堡最近的骑士的距离,那有请下一位入侵者。粗算一下复杂度觉得怎么写都ok就写了个最原始的三次循环于是就是众人中跑的最慢的,附上代码:
#include
#include
#include
FILE*fin,*fout;
int w[1005][1005]={0};
int n,m,cx,cy,ans=0,min=2147483631;
int main()
{
int i,j;
fin=fopen("nightofknights.in","r");
fout=fopen("nightofknights.out","w");
fscanf(fin,"%d%d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
fscanf(fin,"%d",&w[i][j]);
if(w[i][j]==3)
{
cx=i;
cy=j;
}
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
if(w[i][j]==1)
{
if(abs(cx-i)+abs(cy-j)