无压力水题模拟赛
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号
浙公网安备 33010602011771号