无压力水题模拟赛
Day1
| 题目名称 | Little Rooks | Diablo Items | paid Roads |
| 可执行文件名 | Rooks | Items | Roads |
| 输入文件名 | Rooks.in | Items.in | Roads.in |
| 输出文件名 | Rooks.out | Items.out | Roads.out |
| 每个测试点时限 | 1s | 1s | 1s |
| 测试点个数 | 10 | 10 | 10 |
| 每个测试点分值 | 10 | 10 | 10 |
| 内存限制 | 128M | 128M | 128M |
提交源程序须加后缀
| 对于Pascal语言 | rooks.pas | Items.pas | Roads.pas |
| 对于C语言 | rooks.c | Items.c | Roads.c |
| 对于C++语言 | rooks.cpp | Item.cpp | Roads.cpp |
文件名均小写。
Little Rooks
【题目描述】
给定一个n*n的方形棋盘,和k个棋子,这k个棋子在国际象棋中被称为——rooks,他和中国象棋中的车有着相同的攻击规则。问,在这个棋盘上,有多少种方案放下这k个棋子,并使得他们不互相攻击。
【输入格式】
输入有多组,每组数据仅一行两个用空格隔开的整数n和k,含义如上。0 0代表文件的结束。
【输出格式】
对于每组输入数据有且仅有一个整数代表可以成立的放置的方案数。
【输入样例】
4 4
0 0
【输出样例】
24
【数据范围】
所有的答案在int64以内
N<=11
K<=N^2
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n,k;
long long C(int m,int n){
long long tot=1;
for (long long i=k+1;i<=n;i++){
tot*=i;
}
for (int i=n-k;i>1;i--){
tot/=i;
}
return tot;
}
long long A(int n){
long long tot=1;
for (int i=2;i<=n;i++) tot*=i;
return tot;
}
int main(){
freopen("rooks.in","r",stdin);
freopen("rooks.out","w",stdout);
while (cin>>n>>k){
if (n==0 && k==0) break;
if (k>n) cout<<0<<endl;else
cout<<C(k,n)*C(k,n)*A(k)<<endl;
}
return 0;
}
Paid Roads
【题目描述】
这里有一个地图,嗯~准确的说是一个藏宝图。你在1号点,宝藏在n号点,所有的点编号1~n,这块宝底的地形是很奇怪的,每两个点之间有两条通路,两个通路的长度是不一样的,可能会有一条比较短,你可以任选一条,但是其中一条你只有在之前经过某个点的时才能通行,就好像这条路的通行证在那个点上一样。现在想知道怎么样走才能以最短的路程到达藏宝点。
【输入格式】
第一行两个用空格隔开的整数n和m分别表示节点的编号个数和该藏宝点路径条数。
第二行到第m+1行每行5个整数a,b,c,la,lb描述从a点到b点的有向路,la表示之前经过c后,可以从a到b的路径长度,lb表示随时都可以同行的a到b的路径长度。
【输出格式】
一行一个整数表示的是从1到n的最短路程。如果没有路输出‘impossible’。
【输入样例】
4 5
1 2 1 10 10
2 3 1 30 50
3 4 3 80 80
2 1 2 10 10
1 3 2 10 50
【输出样例】
110
【数据范围】
N,m<=10
la,lb<=maxlongint
#include <cstdio>
#include <cstring>
#include <iostream>
#define INF 2147483647
using namespace std;
int v[20];
int n,m,ans;
struct edge{
int x,y,la,lb,next;
}e[100000];
int k[20];
int tot;
void add(int a,int b,int c,int la,int lb){
e[++tot].x=b;
e[tot].y=c;
e[tot].la=la;
e[tot].lb=lb;
e[tot].next=k[a];
k[a]=tot;
}
void dfs(int x,int sum){
if (x==n){
if (ans>sum) ans=sum;
return;
}
for (int t=k[x];t;t=e[t].next){
if (v[e[t].x]<4){
++v[e[t].x];
if (v[e[t].y]) dfs(e[t].x,sum+e[t].la);
else dfs(e[t].x,sum+e[t].lb);
--v[e[t].x];
}
}
}
int main(){
freopen("roads.in","r",stdin);
freopen("roads.out","w",stdout);
cin>>n>>m;
for (int i=1;i<=m;i++){
int a,b,c,la,lb;
cin>>a>>b>>c>>la>>lb;
add(a,b,c,la,lb);
}
v[1]=1;
ans=INF;
dfs(1,0);
if (ans<INF) cout<<ans<<endl;else cout<<"impossible"<<endl;
return 0;
}
Diablo Items
【题目描述】
Diablo II中,有两种物品:普通物品和魔法物品。显然,魔法物品有普通物品没有的神奇力量。
魔法物品和普通物品都可以被卖掉:一个普通物品只有一个价值Pi;而一个魔法物品有两个价值Pi1和Pi2,当使用购买的魔法卷轴鉴定过这个魔法物品以后,它的价值就变为Pi2,否则它只具有Pi1的价值(当然Pi2一定要大于Pi1)。鉴定一个魔法物品需要花费Q来购买一个魔法卷轴,每个魔法卷轴只能使用一次。
你的手中有一些物品。对于普通物品,你已经知道了它们的价值Pi;对于魔法物品,你已经知道了它们的价值Pi1和Pi2。
现在,你想要把它们全部卖掉,以得到最大的收益。
注意:
1. 开始时,你的收中没有钱,无法购买卷轴。
2. 开始时,没有任何魔法物品被卷轴鉴定过。
3. 如果你的手中有足够多的钱,你可以购买足够多的卷轴,但你手中的剩余的钱不能为负。
【输入格式】
每个测试点有多组测试数据:
对于每组测试数据:
第一行两个整数N和Q,N表示拥有物品的数量,Q表示购买一个魔法卷轴的花费。
第二行..第N+1行每行有一个整数或两个整数,如果为一个数,表示这件物品是普通物品,价值为Pi,否则为魔法物品两个价值为Pi1和Pi2。
【输出格式】
对于每组测试数据:
一个整数,即最大的收益。
【样例输入】
2 10
5
8
2 10
10
10 100
【样例输出】
13
100
【数据范围】
0<=N<=1000
Q<=30000
Pi<=10000
Pi1<Pi2<=10000
#include <cstdio>
#include <cstring>
int n,p,m;
int a[1100][4];
int f[11000];
int cost;
inline int min(int a,int b){
if (a<0) return b;
if (b<0) return a;
if (a<b) return a;else return b;
}
void init(){
m=0;
cost=0;
for (int i=1;i<=n;i++){
int x=0;
bool flag=false;
char c=getchar();
while (c<'0' && c>'9') c=getchar();
while (c!='\n'){
x=x*10+c-'0';
c=getchar();
if (c==' '){
flag=true;
a[++m][1]=x;
x=0;
c=getchar();
}
}
if (!flag) cost+=x;
else{
a[m][2]=x;
a[m][3]=x-a[m][1]-p;
if (x-p<a[m][1]){
cost+=a[m][1];
m--;
}
}
}
}
int run(){
int sum=0;
if (cost>=p || m==0){
sum=cost;
for (int i=1;i<=m;i++){
sum+=a[i][2]-p;
}
return sum;
}
int need=-cost+p;
memset(f,255,sizeof(f));
f[0]=0;
for (int i=1;i<=m;i++){
for (int j=need;j>=0;j--){
if (f[j]!=-1){
int next=j+a[i][1];
next=min(next,need);
f[next]=min(f[next],f[j]+a[i][3]);
}
}
}
if (f[need]==-1){
sum=cost;
for (int i=1;i<=m;i++){
sum+=a[i][1];
}
return sum;
}else{
sum+=cost;
for (int i=1;i<=m;i++){
sum+=a[i][2]-p;
}
return sum-f[need];
}
}
int main(){
freopen("items.in","r",stdin);
freopen("items.out","w",stdout);
while (scanf("%d%d\n",&n,&p)!=EOF){
init();
printf("%d\n",run());
}
return 0;
}
无压力水题模拟赛
Day2
|
题目名称 |
MEETING |
toy |
lights |
|
可执行文件名 |
MEETING |
toy |
lights |
|
输入文件名 |
MEETING.IN |
toy.in |
lights.in |
|
输出文件名 |
MEETING.OUT |
toy.out |
lights.out |
|
每个测试点时限 |
1s |
1s |
1s |
|
测试点个数 |
10 |
10 |
10 |
|
每个测试点分值 |
10 |
10 |
10 |
|
内存限制 |
128M |
128M |
128M |
提交源程序须加后缀
|
对于Pascal语言 |
MEETING.pas |
toy.pas |
lights.pas |
|
对于C语言 |
MEETING.c |
toy.c |
lights.c |
|
对于C++语言 |
MEETING.cpp |
toy.cpp |
lights.cpp |
文件名均小写。
Meeting
【题目描述】
Spray 和 Ray 想要在X时刻和Y时刻之间的某个时候会面,但是这两个人都不是很准时的……所以它们没有商定会面的确切时间。但是它们商量好,谁要是先到了,就等对方Z分钟时间。但是它们两个都会在X点和Y点之间的某时刻出现,只是不一定会碰到。
现在,请你计算他们两个碰面的概率。
【输入格式】
输入数据有多组测试数据
每组测试数据包含两个整数X和Y(0<=x<y<=24)和一个实数Z(0<Z<=60*(Y-X))
【输出格式】
对于每组测试数据
输出一行,为计算出的概率,保留小数点后6位,第7位四舍五入。
【输入样例】
11 12 20
【输出样例】
0.555556
#include <cstdio>
#include <iomanip>
#include <iostream>
using namespace std;
double c;
int a,b;
int main(){
freopen("meeting.in","r",stdin);
freopen("meeting.out","w",stdout);
while (scanf("%d %d %lf",&a,&b,&c)!=EOF){
double t=b-a-c/60.0;
double ans=((b-a)*(b-a)-t*t)/(b-a)/(b-a);
printf("%.6lf\n",ans);
}
return 0;
}
Toy Bricks
【题目描述】
Ray又在NPC问题了:这里有一个箱子,还有若干个玩具。
我们可以假设玩具的数量是没有上限的。我们还知道这个箱子是不规则的,或者可以说,他的外形比较像一个矩形,但是内部却有很多突起,这些突起很可恶,他可以一直突到玩具的顶盖部。为了简化这个NPC问题,Ray只保留了一种形状的玩具
Ray想知道对于一个给定的箱子,最多可以放下多少个这样的玩具。
【输入格式】
第一行两个用空格隔开的整数n 和 m 表示玩具想的长度和宽度
第二行到第n+1行,每行m个用空格隔开的字符‘#’’.‘;’#’表示这里是一个障碍物。’.’表示这里可以放东西。
【输出格式】
一行一个整数表示最多的玩具个数
【输入样例】
5 4
#.#.
…#
#..#
#...
##.#
【输出样例】
2
【数据范围】
0<=n<=100
0<=m<=10
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int T;
int n,m;
int st[130];
int tot;
int num[110];
int dp[110][130][130];
int cur[110];
int ans;
int max(int a,int b){return a>b?a:b;}
bool ok(int i){//判断可行状态
if ((i & (i << 1)) || (i & (i >> 1))) return 0;
for (int k=1;k<=m;k++){
if ((i & (1 << (k-1))) && (i & (1 << (k+1)))) return 0;
}
return 1;
}
void build(){//枚举得到所有可行状态
for (int i=0;i<1 << m;i++){
if (!(i & 1) && !(i & (1 << (m-1))))
if (ok(i)) st[++tot]=i;
}
}
int getnum(int x){//得到一个状态中放置的玩具个数
int cnt=0;
while (x){
++cnt;
x &= (x-1);
}
return cnt;
}
bool fit(int x,int i){//判断这一行和上一行(下一行) 的障碍是否冲突
if (cur[i] & x) return 0;
return 1;
}
bool fit2(int x,int i){//判断这一行的状态和这一行的障碍是否冲突
if (cur[i] & x) return 0;
if (cur[i] & (x >> 1)) return 0;
if (cur[i] & (x << 1)) return 0;
return 1;
}
bool check(int a,int b){//判断这一行和上一行的状态是否可行
for (int i=1;i<m-1;i++){
if (a & (1 << i))
if ((b & (1 << i)) || (b & (1 << (i-1))) || (b & (1 << (i+1)))) return 0;
}
return 1;
}
bool check2(int a,int b){//判断这一行的状态和前两行的状态是否可行
if (a & b) return 0;
return 1;
}
int main(){
freopen("toy.in","r",stdin);
freopen("toy.out","w",stdout);
while (scanf("%d%d\n",&n,&m)!=EOF){
tot=0;
memset(cur,0,sizeof(cur));
build();
for (int i=1;i<=n;i++){
for (int j=1;j<=m;j++){
char c;
scanf("%c",&c);
if (c=='#') cur[i]+=(1 << (j-1));
}
scanf("\n");
}
memset(dp,-1,sizeof(dp));
for (int i=1;i<=tot;i++){
num[i]=getnum(st[i]);
if (fit(st[i],1) && fit2(st[i],2)){
dp[2][1][i]=num[i];
}
}
for (int i=3;i<=n;i++){
for (int j=1;j<=tot;j++){
if (fit2(st[j],i))
for (int k=1;k<=tot;k++){
if (fit2(st[k],i-1) && fit(st[j],i-1) && fit(st[k],i))
if (check(st[j],st[k]))
for (int l=1;l<=tot;l++){
if (dp[i-1][l][k]!=-1)
if (check2(st[l],st[j]))
dp[i][k][j]=max(dp[i][k][j],dp[i-1][l][k]+num[j]);
}
}
}
}
for (int i=1;i<=tot;i++){
if (fit2(st[i],n-1) && fit(st[i],n)) ans=max(ans,dp[n][i][1]);
}
printf("%d\n",ans);
}
return 0;
}
Lights
【题目描述】
Spray来到了zz城。这个城市的的交通规则非常奇怪,城市公路通过路口相连,两个不同路口之间最多只有一条直达公路。公路的起止点不会是同一路口。在任意一条公路上顺不同方向走所需时间相同。每一个路口都有交通灯,这些交通灯在某一时刻要么是蓝色,要么是紫色。同一个灯上2个颜色的维持时间受到定期调控,总是蓝色持续一段时间,紫色持续一段时间。交通规则规定两个路口可以通车仅当公路两边交通灯的颜色相同(也就是说只要你在A路口看见A与B的交通灯颜色相同,那么就可以走上A-B这条路并到达B路口)。交通工具可以在路口等候。
现在Spray有这个城市的地图,包含:
1. 通过所有公路需要的时间(整数)
2. 每个路口交通灯两种颜色的持续时间(整数)
3. 每个路口交通灯的初始颜色以及初始颜色的持续时间(整数).
你的任务是帮Spray找到一条从起点到终点的最快路径(保证路径唯一)。【输入数据】
第一行包含两个整数: 起点和终点的编号.
第二行包含两个整数: N, M. (2 ≤ N ≤ 300 ,1 ≤ M ≤ 14000)
接下来 N 行描述 N 个路口的情况.
第i+2行 是 i 号路口的信息: Ci, riC, tiB, tiP 。
其中字符 Ci 要么是“B”代表蓝色,要么是“P”代表紫色,表示 i 的起始颜色. riC, tiB, tiP 分别表示初始颜色,蓝色,紫色的持续时间,
(1 ≤ tiC ≤ 100 . 1 ≤ riC ≤ tiC )
最后的 M 行表示关于 M 条公路的信息。包含: i, j, lij 。i 和 j 号路口被这条路连接. lij 是通过i到j这条公路需要的时间。(1 ≤ lij ≤ 100)
【输出数据】
如果存在最短路径:
第一行输出最短时间。
第二行是一个对应第一行答案的路口编号表,从起点到终点输出路口编号,数字之间用空格隔开(即输出路径方案)。
如果不存在,直接输出“0”。
【样例输入】
1 4
4 5
B 2 16 99
P 6 32 13
P 2 87 4
P 38 96 49
1 2 4
1 3 40
2 3 75
2 4 76
3 4 77
【样例输出】
127
1 2 4
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define M 100000
int n,m;
int st,en;
struct NODE{
int c,b,p,r;
}node[310];
struct EDGE{
int x,next,l;
}edge[28100];
int k[310];
int f[M];
int d[310];
bool v[310];
int tot,sum;
int pre[310];
int len[310];
int ans;
int min(int a,int b){return a<b?a:b;}
void add(int a,int b,int c){
edge[++tot].x=b;
edge[tot].l=c;
edge[tot].next=k[a];
k[a]=tot;
}
int wait(int x,int y,int t){
int i,j;
//初始状态比较
int tt=t;
if (tt<node[x].r) i=node[x].c;
else{
tt=(t-node[x].r) % (node[x].p+node[x].b);
int dd;
if (node[x].c==0) dd=node[x].b;else dd=node[x].p;
if (tt>=0 && tt<dd) i=!node[x].c;else i=node[x].c;
}
//------------------------------
tt=t;
if (tt<node[y].r) j=node[y].c;
else{
tt=(t-node[y].r) % (node[y].b+node[y].p);
int dd;
if (node[y].c==0) dd=node[y].b;else dd=node[y].p;
if (tt>=0 && tt<dd) j=!node[y].c;else j=node[y].c;
}
if (i==j) return 0;
//不同进入第一次变灯
int tx,ty;
if (t<node[x].r) tx=node[x].r;
else{
int mid=(t-node[x].r) % (node[x].b+node[x].p);
int dd;
if (node[x].c==0) dd=node[x].b;else dd=node[x].p;
if (mid>=0 && mid<dd) tx=t-mid+dd;
else tx=t-mid+(node[x].b+node[x].p);
}
//------------------------------
if (t<node[y].r) ty=node[y].r;
else{
int mid=(t-node[y].r) % (node[y].b+node[y].p);
int dd;
if (node[y].c==0) dd=node[y].b;else dd=node[y].p;
if (mid>=0 && mid<dd) ty=t-mid+dd;
else ty=t-mid+(node[y].b+node[y].p);
}
if (tx!=ty) return min(tx,ty)-t;
//第一次编订后仍不同进入第二次变灯
int mid=(tx-node[x].r) % (node[x].b+node[x].p);
int dd;
if (node[x].c==0) dd=node[x].b;else dd=node[x].p;
if (mid>=0 && mid<dd) tx=tx-mid+dd;
else tx=tx-mid+(node[x].b+node[x].p);
//------------------------------
mid=(ty-node[y].r) % (node[y].b+node[y].p);
if (node[y].c==0) dd=node[y].b;else dd=node[y].p;
if (mid>=0 && mid<dd) ty=ty-mid+dd;
else ty=ty-mid+(node[y].b+node[y].p);
if (tx!=ty) return min(tx,ty)-t;
//第二次变灯后仍不同进入第三次变灯
mid=(tx-node[x].r) % (node[x].b+node[x].p);
if (node[x].c==0) dd=node[x].b;else dd=node[x].p;
if (mid>=0 && mid<dd) tx=tx-mid+dd;
else tx=tx-mid+(node[x].b+node[x].p);
//------------------------------
mid=(ty-node[y].r) % (node[y].b+node[y].p);
if (node[y].c==0) dd=node[y].b;else dd=node[y].p;
if (mid>=0 && mid<dd) ty=ty-mid+dd;
else ty=ty-mid+(node[y].b+node[y].p);
if (tx!=ty) return min(tx,ty)-t;
//第三次编订后仍不同进入第四次变灯
mid=(tx-node[x].r) % (node[x].b+node[x].p);
if (node[x].c==0) dd=node[x].b;else dd=node[x].p;
if (mid>=0 && mid<dd) tx=tx-mid+dd;
else tx=tx-mid+(node[x].b+node[x].p);
//------------------------------
mid=(ty-node[y].r) % (node[y].b+node[y].p);
if (node[y].c==0) dd=node[y].b;else dd=node[y].p;
if (mid>=0 && mid<dd) ty=ty-mid+dd;
else ty=ty-mid+(node[y].b+node[y].p);
if (tx!=ty) return min(tx,ty)-t;
//第四次编订后仍不同进入第五次变灯
mid=(tx-node[x].r) % (node[x].b+node[x].p);
if (node[x].c==0) dd=node[x].b;else dd=node[x].p;
if (mid>=0 && mid<dd) tx=tx-mid+dd;
else tx=tx-mid+(node[x].b+node[x].p);
//------------------------------
mid=(ty-node[y].r) % (node[y].b+node[y].p);
if (node[y].c==0) dd=node[y].b;else dd=node[y].p;
if (mid>=0 && mid<dd) ty=ty-mid+dd;
else ty=ty-mid+(node[y].b+node[y].p);
if (tx!=ty) return min(tx,ty)-t;
//无法通行
return -1;
}
//最短路求解
void SPFA(){
int head=0,tail=1;
memset(d,63,sizeof(d));
memset(v,0,sizeof(v));
d[st]=0;
v[st]=true;
f[tail]=st;
while (head!=tail){
head++;
if (head==M) head=1;
int x=f[head];
v[x]=false;
for (int t=k[x];t;t=edge[t].next){
int tmp=wait(x,edge[t].x,d[x]);
if (tmp!=-1 && d[edge[t].x]>d[x]+tmp+edge[t].l){
d[edge[t].x]=d[x]+tmp+edge[t].l;
pre[edge[t].x]=x;
if (!v[edge[t].x]){
v[edge[t].x]=true;
tail++;
if (tail==M) tail=1;
f[tail]=edge[t].x;
}
}
}
}
ans=d[en];
}
int main(){
freopen("lights.in","r",stdin);
freopen("lights.out","w",stdout);
scanf("%d%d\n",&st,&en);
if (st==en){
printf("0\n%d\n",st);
return 0;
}
scanf("%d%d\n",&n,&m);
for (int i=1;i<=n;i++){
char c;
scanf("%c%d%d%d\n",&c,&node[i].r,&node[i].b,&node[i].p);
node[i].c=('B'==c);
}
for (int i=1;i<=m;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
SPFA();
if (ans>100000){printf("0\n");return 0;}
printf("%d\n",ans);
len[++sum]=en;
int t=pre[en];
while (t){
len[++sum]=t;
t=pre[t];
}
for (int i=sum;i>1;i--) printf("%d ",len[i]);
printf("%d\n",len[1]);
return 0;
}

浙公网安备 33010602011771号