"科林明伦杯"哈尔滨理工大学第六届程序设计团队赛(12.10)

来源:互联网 发布:数据来源英文 编辑:程序博客网 时间:2024/05/01 19:59
"科林明伦杯"哈尔滨理工大学第六届程序设计团队赛

水题已去除。。
B题  Time
原题链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=2315

Description

Kim是一个掌控时间的大师。不同于一般人,他习惯使用秒来计算时间。如果你问他现在是几点,他会告诉你现在是今天的xxxx秒。Mik想要考考Kim。他想知道从某一天的00:00:00开始,经过s秒后是哪一天。但是Mik不会计算答案,他需要你的帮助。

注意:我们认为一天从00:00:00开始,到23:59:59结束。00:00:00经过1秒后是00:00:01;从00:00:00开始,加86400(60*60*24)秒后就是下一天的00:00:00.

Input

第一行一个整数T表示数据组数。

接下来T行,每行一个日期yyyy-MM-dd,接下来一个整数s表示s秒。

Output

对于每个输入,输出一行yyyy-MM-dd 表示答案。对于不足两位的数要补齐前导0。

Sample Input
32016-12-10 10002016-02-28 864002016-01-01 1000000
Sample Output
2016-12-102016-02-292016-01-12
Hint

T<=100

s<=2147483647

日期在1800-01-01到2100-01-01之间


闰年的判断:

1.能被4整除且不能被100整除的为闰年.

2.能被400整除的是闰年.

代码:
#include<stdio.h>bool isleap(int y){    if(y%4==0&&y%100!=0||y%400==0)        return 1;    return 0;}int maxday(int i,int y){    if(i==2)    {        if(isleap(y))            return 29;        else            return 28;    }    else if(i==1||i==3||i==5||i==7||i==8||i==10||i==12)        return 31;    else        return 30;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int y,m,d,s;        scanf("%d-%d-%d%d",&y,&m,&d,&s);        s=s/86400;        for(int i=1; i<=s; i++)        {            d++;            if(d>maxday(m,y))            {                d-=maxday(m,y);                m++;            }            if(m==13)                y++,m=1;        }        printf("%d-%02d-%02d\n",y,m,d);    }    return 0;}

ps:由于以前这类题就写过两道,比赛的时候写的手忙脚乱的,这么基础的题最后还是没A。。哭
D题 Game
Description

Kim is a college student who love computer games, but unfortunately his school just published a rule that Games should disappear in the campus , that means nobody can play computer games in school, including the students dormitory. However, the student don’t take it seriously, that’s why the manager of the school gets so angry that he decided to go to the dormitory to punish the students. You should know the manager will punish those students who is playing games at the moment he enter the room, and leave immediately if nobody is playing game in this room.

  Kim is a talented game player , in fact, he is the Carry of a famous Gaming club, so he needs time to practice he’s skills . And luckily , Kim’s roommate Mik is a Geek(also a Kim fan), he hacked the manager’s computer and get the timetable of the manager, and tell Kim when will the manager come to their room tomorrow. A big E-sport Event is around the corner, so Kim list m skills he should practice, each skill takes some time to practice and improve Kim’s skill by some points. You should calculate the max total improvement points Kim can get. Note any skills can be practiced any times , including 0.

Input


The first line contains a integer T ( T <= 10 ), then T cases follows.

In each case, there are 3 parts of input. 

The first part contains 3 integers L, n, m in a single line.Range[0, L] is the time Kim decide to practice , n is the times manager would enter his room, m indicate the total number of the skills. 

The second part contains n integers ti(0 <= ti <= L) in a single line, means the manager would enter his room at ti. Note that ti is giving in the increasing order. 

The third part has m lines , each line contains two integers ci, vi, means this skill needs ci minutes to practice and can make vi points improvement.

L<=500, n<=10, m<=100.


Output

For each case, you should output the max points Kim can improve.

Sample Input
26 1 332 32 42 56 2 32 42 32 42 5
Sample Output
1015
Hint

Note that Kim will be catch playing games any time in the interval of his practicing, excluded the beginning and the ending of each practice time. 

Sample 1:

D.Game sample 1

Sample 2:

D.Game sample 2

代码:
#include<stdio.h>#include<string.h>#define max(a,b)  (a>b?a:b)#define N  500+10int a[11],vi[101],ci[101],dp[N];int l,n,m;void mulpack(int y){    int i,j;    for(i=1; i<=m; i++)        for(j=ci[i]; j<=y; j++)            dp[j]=max(dp[j],dp[j-ci[i]]+vi[i]);}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int i,s=0;        scanf("%d%d%d",&l,&n,&m);        for(i=1; i<=n; i++)            scanf("%d",&a[i]);        a[0]=0,a[n+1]=l;        for(i=1; i<=m; i++)            scanf("%d%d",&ci[i],&vi[i]);        for(i=0; i<=n; i++)//分段,求多个多个完全背包        {            memset(dp,0,sizeof(dp));            mulpack(a[i+1]-a[i]);            s+=dp[a[i+1]-a[i]];        }        printf("%d\n",s);    }    return 0;}


ps:很基础的完全背包。。

E题 Mod
Description

Kim刚刚学会C语言中的取模运算(mod)。他想要研究一下一个数字A模上一系列数后的结果是多少。帮他写个程序验证一下。

Input

第一行一个整数T代表数据组数。

接下来T组数据,第一行一个整数n,接下来n个数字ai

接下来一行一个整数m,接下来m个数字bi。

Output

对于每个bi,输出bi%a1%a2%...%an 。

Sample Input
1410 9 5 7514 8 27 11 25
Sample Output
43210
Hint

在C语言中,A mod B 是 a%b

样例解释:

14%10%9%5%7=4

8%10%9%5%7=3

...

数据范围:

1<=n<=100000

1<=m<=100000

1<=ai<=1000000000

0<=bi<=1000000000

代码:
#include<stdio.h>#define ll long long int#define N 100000+10ll a[N];int main(){    int t;    scanf("%d",&t);    while(t--)    {        ll n,m,k,i;        scanf("%lld",&n);        for(i=1;i<=n;i++)            scanf("%lld",&a[i]);        ll tot=1;        for(i=2;i<=n;i++)//找出单调递减的元素            if(a[i]<a[tot])        {            tot++;           a[tot]=a[i];        }        n=tot;        scanf("%lld",&m);        for(i=1;i<=m;i++)        {            scanf("%lld",&k);            while(1)            {                ll x=0,y=n+1;                while(y-x>1)//利用二分法不断地取模                {                    ll mid=x+(y-x)/2;                    if(a[mid]<=k)                        y=mid;                    else                        x=mid;                }                if(y==n+1)//直到k比所有元素都小                    break;                k=k%a[y];            }            printf("%lld\n",k);        }    }    return 0;}

ps:

中等题。注意到不断取模下去会越来越小,而且一个数模a之后再模b,如果ab小那么模b就没有意义了。所以对输入的a数组剔除所有没用的数,剩下一个递减的数组。在这个数组上,每次二分找到距离当前x最接近且大于x的数,模上这个数重复这一过程即可。这个过程不会重复很多次。很快这个数就会小于所有的a,这时就获得了答案。(二分还是很重要呀呀)

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

下面都是对我来说比较难的题了,先存起来。(待补)

F题Number Game

原题链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=2319

Description

There are n items and two players, Kim and you. For each player and for each item, the value of the item for this player is known. Denote values of the i-th item for the first and the second player as ai and bi correspondingly.

Players take the items in turns. Kim starts the game. Kim is greedy: each turn, he chooses the item which has the maximal ai among the remaining items. If there are several such items, he can take any one of them. What is the maximal possible sum of values bi of items taken by the second player that he can guarantee regardless of the first player’s moves?

Input


The first line is an integer T, describes the number of tests. Then T tests.

Each case contains a single integer n, the number of items.

The second line contains n numbers, i-th is equal to ai, the value of the i-th item for Kim.

The third line contains n numbers, i-th is equal to bi, the value of the i-th item for the second player.


Output

Output a single number: the maximal sum of values bi of items taken by the second player that he can guarantee.

Sample Input
1
51 2 3 4 52 3 4 5 6
Sample Output
8
Hint

1 <= n <= 1000

ai and bi are integers from 1 to 10e9

标程:
#include <cstdio>#include <iostream>#include <cstring>#include <stack>#include <vector>#include <set>#include <algorithm>#include <cmath>#include <queue>#include <sstream>#include <map>#include <time.h> #define INF 0x3f3f3f3f#define EPS 1e-10#define PI acos(-1.0)#define LL long long#define scan(x) scanf("%d",x)#define rep(i,a,b) for(int i=a;i<b;i++)#define PII pair<int,int>#define sqr(x) ((x)*(x))#define IN freopen("in.txt","r",stdin);#define OUT freopen("out.txt","w",stdout);using namespace std;#define N 1111#define M 63333struct  node{int ai,bi;}a[N];bool cmp(node a,node b){return a.ai==b.ai?a.bi>b.bi:a.ai>b.ai;}priority_queue<int>que;int main(){//if (2&1)cout<<"r"<<endl;    int n,T;    scan(&T);    while (T--)    {scan(&n);rep(i,0,n)scan(&a[i].ai);rep(i,0,n)scan(&a[i].bi);sort(a,a+n,cmp);rep(i,1,n){cout<<i<<" "<<a[i].ai<<endl;if (i&1) {/*cout<<i<<" "<<a[i].ai<<endl;*/que.push(-a[i].bi);}else if (a[i].bi>-que.top()) {que.pop();que.push(-a[i].bi);}}LL ans=0;while (!que.empty()){ans=ans-que.top();que.pop();}cout<<ans<<endl;}    return 0;    }

ps:

难题。这是一道贪心问题。把数据按ai从大到小排序,ai相同的bi从大到小排序。根据题意a会按照排好的顺序每次拿最大的。那么我们的贪心思路就是每次如果我们可以用当前的bi换下一个会被拿走的bi,从而使得bi的和变大,那我们就交换。这样贪心下去就可以得到答案。具体实现的时候可以用一个堆来动态的获得当前的最大(最小)值。

G题OX

原题链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=2320

Description

Kim喜欢玩井字棋。但是他从来都没有赢过:)Kim非常好奇井字棋是否有一个必胜的策略。

给定一个局面,以及下一步该谁走(o或x),请判断在双方都足够聪明的情况下(双方一直采用最优策略),是否有一个人能够获胜(或者平局)。

Input

第一行一个整数T代表数据组数。

接下来T组数据,每组数据三行,每行三个字符串(o 或 x 或 .)

o表示这个位置有一个o

x表示这个位置有一个x

.表示这个位置是空的

接下来一行一个字符串(o 或 x),表示下一步该这个人走了。

Output

如果x有必胜策略,输出 “x win!”(不含引号)。

如果o有必胜策略,输出 “o win!”(不含引号)。

如果双方在最有策略下只能平局,输出 “tie!” (不含引号)。

Sample Input
2. . .. o .x x .x. . .. . .. . xo
Sample Output
x win!tie!
Hint

T <= 10


标程:
#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <iostream>#include <map>#define next nxt#define FOR(i,j,k) for(int i=j;i<=k;i++)using namespace std;string s[5][5];struct state{int board[4][4];void print(){FOR(i,1,3){FOR(j,1,3)cout<<board[i][j]<<" ";cout<<endl;}}};bool operator < (const state& a,const state& b){FOR(i,1,3)FOR(j,1,3)if (a.board[i][j]!=b.board[i][j])return a.board[i][j]<b.board[i][j];return false;}map<state,int> fwin;state makestate(){state ans;FOR(i,1,3){FOR(j,1,3){if (s[i][j]=="o")ans.board[i][j]=0;else if (s[i][j]=="x")ans.board[i][j]=1;else ans.board[i][j]=-1;}}return ans;}int check(state now){FOR(i,1,3){if (now.board[i][1]==now.board[i][2] && now.board[i][1]==now.board[i][3]){if (now.board[i][1]!=-1)return now.board[i][1];}}FOR(j,1,3){if (now.board[1][j]==now.board[2][j] && now.board[1][j]==now.board[3][j]){if (now.board[1][j]!=-1)return now.board[1][j];}}if (now.board[1][1]==now.board[2][2] && now.board[1][1]==now.board[3][3]){if (now.board[1][1]!=-1)return now.board[1][1];}if (now.board[1][3]==now.board[2][2] && now.board[1][3]==now.board[3][1]){if (now.board[1][3]!=-1)return now.board[1][3];}FOR(i,1,3)FOR(j,1,3)if (now.board[i][j]==-1)return -1;//continuereturn 2;//tie}int search(state now,int next){//0-win 1-tie 2-losenow.print();cout<<next<<endl;if (fwin.find(now)!=fwin.end())return fwin[now];int temp=check(now);cout<<"check "<<temp<<endl;if (temp==2){fwin[now]=1;return 1;}else if (temp==(next^1)){fwin[now]=2;return 2;}else if (temp==next) {fwin[now]=0;return 0;}int mark=0;FOR(i,1,3){FOR(j,1,3){if (now.board[i][j]==-1){state temp=now;temp.board[i][j]=next;int rst=search(temp,next^1);mark=max(mark,rst);}}}if (mark==0)fwin[now]=2;else if (mark==1)fwin[now]=1;else fwin[now]=0;return fwin[now];}int main (int argc, char *argv[]){std::ios::sync_with_stdio(false);int noc;cin>>noc;while (noc--){FOR(i,1,3)FOR(j,1,3){cin>>s[i][j];}int fst;string temp,ano;cin>>temp;if (temp=="o")fst=0 , ano="x";else fst=1 , ano="o";fwin.clear();int key=search(makestate(),fst);if (key==0)cout<<temp<<" "<<"win!"<<endl;else if (key==1)cout<<"tie!"<<endl;else cout<<ano<<" "<<"win!"<<endl;}return 0;}

ps:

中等题。博弈搜索。实际上一共9个位置,每个位置3个状态,一共只有3^9=19683种状态。我们可以暴力枚举出所有的状态,做一个搜索即可。对于当前的一个状态,如果其后继状态里存在先手必败的状态,那么这个状态是先手必胜的;如果其后继状态里没有先手必败的状态但有平局状态,那么这个状态是平局态;如果其后继状态里都是先手必胜态,那么当前状态只能是先手必败了

H题Permutation

原题链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=2321

Description

n个人排成一队,队头的人编号为1,后面的人编号分别为2,3,…,n. 1号人前面没有人,i号人的前面是i-1。 现在Kim想让这n个人重新排队,要求重新排队后编号为i的人前面不能是i-1。问有多少种排队的方法。方案数可能很大,输出答案模1e9+7。

Input

第一行一个整数T,表示有T组数据。

接下来T行,每行一个整数n。表示有n个人排成一队。

Output

对于每个n,输出答案 mod 1000000007。

Sample Input
214
Sample Output
111
Hint

T<=2000

n<=2000000

n=4 时,原队列为 1 2 3 4。所有合法的新队列如下:

4 1 3 2

4 3 2 1

4 2 1 3

3 2 1 4

3 2 4 1

2 1 4 3

2 4 3 1

2 4 1 3

3 1 4 2

1 3 2 4

1 4 3 2

一共有11种。


标程:
#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <iostream>#define FOR(i,j,k) for(int i=j;i<=k;i++)using namespace std;typedef long long LL;const LL mod = 1000000000+7;LL f[2000000+233];int main (int argc, char *argv[]){    std::ios::sync_with_stdio(false);    f[0]=f[1]=1;    FOR(i,2,2000000)    {        f[i]=i*f[i-1]+(i-1)*f[i-2];        f[i]%=mod;    }    int noc;    cin>>noc;    while (noc--)    {        int n;        cin>>n;        cout<<f[n-1]<<endl;    }    return 0;}
ps:

中等题。a(n) = n*a(n-1) + (n-1)*a(n-2), a(0) = 1, a(1) = 1. a(n)代表排列[1,...,n+1]不含有子串[k,k+1]的方案数。所以n的答案为a(n-1)

更加详细的证明可以参考《组合数学》第六章容斥原理及应用6.5节(P113)。(好吧,题解的公式弄不上来)


                                                                                                               I题  Team

原题链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=2322

Description

Kim 正在玩一款手游,在这款游戏中,Kim可以选择若干个角色编成一队作战。为了挑战不同的关卡,Kim需要不断的调整编队阵容。然而随着游戏不断更新,队伍成员变得越来越多,Kim已经记不清哪些角色在队伍中,哪些角色不在队伍中了。请你写一个程序来帮助他。

具体来说,Kim有三种可以执行的操作。

1 x  :把 x 号角色加入队伍。如果x号角色已经在队伍中,什么都不会发生。

2 x  :把 x 号角色从队伍中移除。如果x号角色不在队伍中,什么都不会发生。

3 x  :撤销第x次操作。如果第x次操作已经被撤销,什么都不会发生。

每次操作有一个编号,从1开始。对于3 x操作,第x次操作会被撤销。被撤销的操作相当于没有进行这次操作。

Kim可能撤销一次插入,撤销一次删除,或撤销另一次撤销操作。

现在请你告诉Kim所有操作都结束后,队伍中有几个角色,都是谁。

Input

第一行一个整数T,表示有T组数据。

每组数据第一行两个整数n,m表示一共有n个角色(编号1-n),m个操作。

初始队伍中没有角色。

接下来m行,每行一个操作,格式为

1 x 或 2 x 或 3 x,含义见题目描述。

操作的编号等价于给出操作的顺序。第一个给出的操作是1号,第二个给出的操作是2号,以此类推。

对于3 x 操作,保证 x 小于 这条操作的编号。

Output

对于每组数据,输出两行。

第一行一个整数n,表示最后队伍中有n个人。

接下来一行n个整数,表示队伍中角色的编号,角色编号按照从小到大的顺序输出。

每个编号后面有一个空格,包括最后一个编号。如果第一行n为0,则第二行为一个空行,即没有编号,只有一个换行符)

Sample Input
15 81 11 2 3 21 43 33 51 52 5
Sample Output
21 4 
Hint

T<=10

n<=50000

m<=50000


标程:

#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <iostream>#define FOR(i,j,k) for(int i=j;i<=k;i++)using namespace std;#define MAXN (60000)struct cmd{int type,x;cmd(int type=0,int x=0):type(type),x(x) {};}op[MAXN];bool ban[MAXN],team[MAXN],done[MAXN];int main (int argc, char *argv[]){std::ios::sync_with_stdio(false);int noc;cin>>noc;while (noc--){int n,m;cin>>n>>m;FOR(i,1,m){cin>>op[i].type>>op[i].x;}memset(done,false,sizeof done);memset(ban,false,sizeof ban);memset(team,false,sizeof team);for(int i=m;i>=1;i--){if (ban[i])continue;int temp=op[i].x;if (op[i].type==3){ban[temp]=true;}else if (op[i].type==2){if (!done[temp]){team[temp]=false;done[temp]=true;}}else{if (!done[temp]){team[temp]=true;done[temp]=true;}}}int cnt=0;FOR(i,1,n)if (team[i])cnt++;cout<<cnt<<endl;FOR(i,1,n)if (team[i])cout<<i<<" ";cout<<endl;}return 0;}

ps:

中等题。如果直接模拟,主要问题在于撤销操作。撤销操作会撤销其他撤销操作,模拟起来时间复杂度是n^2的。但是如果我们倒着模拟,对于一个操作,如果是一个撤销操作就打个标记,如果一个操作已经被撤销了就什么都不做。这样就不会连锁撤销了。一个人物究竟在不在队伍里取决于最后一次没有被撤销的操作。

K题Lyne

原题链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=2324

Description

Kim正在玩一款叫Lyne的游戏。在这款游戏中,你需要将相同颜色的点用一条线串联起来。

一共有四种颜色的节点:红、绿、蓝、白。游戏的目标是将所有相同颜色的节点一条线连接起来。除此以外有一些特殊的规则:

1、对于每种颜色,有两个特殊节点,每种颜色的连线必须从一个特殊节点开始,从另一个特殊节点结束。

2、每条线只能连接相同的颜色。但是白色节点可以和任意颜色相连。所有的白色节点不必要连在一起。

3、红、绿、蓝节点一个点只能被用一次(而且必须被用一次)。但是白色节点可以被使用多次。例如,可以被使用两次,可以被使用三次。

4、每次可以连接上下左右相邻对角相邻的两个合法节点。连接的线不能交叉或重叠

5、当所有的线都被连好后,所有白的节点必须被用光。例如,必须被用两次,必须被用三次。


下图是这一关的解法

每个点都被用尽了。

下图是一些错误的解法:

有一个白色点没有被用光。

线不能交叉。


现在Kim卡在某关上了,他很好奇有些关卡是否有解。

Input

第一行一个整数T表示一共有T组数据。

每组数据第一行两个整数n和m。表示一共有n行和m列。

接下来n行,每行m个字符串表示关卡地图。

我们用a,b,c代表三种颜色,A,B,C代表对应的特殊节点(起点或终点)。保证如果存在某种颜色,那么这种颜色的特殊节点一定恰好出现两次。

我们用2,3,4代表白色节点,2代表这个节点要被用2次,3代表用3次,以此类推。

注意有些节点是”x”.”x”代表这个节点不能被使用。这种节点没有颜色,不能也不需要被使用。

保证所有输出合法。

Output

对于每组输入,输出一行 “Yes” 表示有解, “No” 表示无解。

Sample Input
24 3A B C2 B 2a b cC 2 A3 3A a ax x xa a A
Sample Output
YesNo
Hint

T<=15

n<=8

m<=4


第一组样例数据就是题目描述中的那一关。

标程:
#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <iostream>#include <vector>#define FOR(i,j,k) for(int i=j;i<=k;i++)using namespace std;int cnta,cntb,cntc;int ax,ay,bx,by,cx,cy;char a[10][10];int dx[]={-1,-1,0,1,1,1,0,-1};int dy[]={0,-1,-1,-1,0,1,1,1};int vis[10][10];bool lined[20][20][20][20];int n,m;vector<string> solution;inline bool check(){FOR(i,1,n)FOR(j,1,m)if (vis[i][j]!=0) return false;return true;}inline void line(int x,int y,int tx,int ty,char c){//solution.push_back(to_string(x)+" "+to_string(y)+"  "+to_string(tx)+" "+to_string(ty));vis[tx][ty]--;lined[x][y][tx][ty]=lined[tx][ty][x][y]=true;}inline void unline(int x,int y,int tx,int ty,char c){//solution.pop_back();vis[tx][ty]++;lined[x][y][tx][ty]=lined[tx][ty][x][y]=false;}inline bool ok(int x,int y,int tx,int ty){if (vis[tx][ty]==0)return false;if (lined[x][y][tx][ty])return false;FOR(i,0,7){if (tx==x+dx[i] && ty==y+dy[i] && lined[x+dx[(i-1+8)%8]][y+dy[(i-1+8)%8]][x+dx[(i+1)%8]][y+dy[(i+1)%8]])return false;}return true;}bool gao(int x,int y,char c,int cnt){if (cnt<1)return check();FOR(i,0,7){if (a[x+dx[i]][y+dy[i]]==c){if (ok(x,y,x+dx[i],y+dy[i])){line(x,y,x+dx[i],y+dy[i],c);if (gao(x+dx[i],y+dy[i],c,cnt-1)==false){unline(x,y,x+dx[i],y+dy[i],c);}else return true;}}else if (a[x+dx[i]][y+dy[i]]<='9' && a[x+dx[i]][y+dy[i]]>='2') {if (ok(x,y,x+dx[i],y+dy[i])){line(x,y,x+dx[i],y+dy[i],c);if (gao(x+dx[i],y+dy[i],c,cnt)==false){unline(x,y,x+dx[i],y+dy[i],c);}else return true;}}else if (a[x+dx[i]][y+dy[i]]==c-'a'+'A' && cnt==1){if (ok(x,y,x+dx[i],y+dy[i])){line(x,y,x+dx[i],y+dy[i],c);if (c=='a'){if (gao(bx,by,'b',cntb-1))return true;else{unline(x,y,x+dx[i],y+dy[i],c);}}else if (c=='b'){if (gao(cx,cy,'c',cntc-1))return true;else{unline(x,y,x+dx[i],y+dy[i],c);}}else if (c=='c'){if (check()==true)return true;else {unline(x,y,x+dx[i],y+dy[i],c);}}}}}return false;}int main (int argc,char *argv[]){std::ios::sync_with_stdio(false);int noc;cin>>noc;FOR(cs,1,noc){solution.clear();cin>>n>>m;cnta=cntb=cntc=0;ax=ay=bx=by=cx=cy=0;memset(vis,0,sizeof vis);memset(lined,false,sizeof lined);FOR(i,0,n+1)FOR(j,0,m+1)a[i][j]='x';FOR(i,1,n){FOR(j,1,m){string cmd;cin>>cmd;a[i][j]=cmd[0];if (a[i][j]=='A')ax=i,ay=j;if (a[i][j]=='B')bx=i,by=j;if (a[i][j]=='C')cx=i,cy=j;if (a[i][j]=='a' || a[i][j]=='A')cnta++;if (a[i][j]=='b' || a[i][j]=='B')cntb++;if (a[i][j]=='c' || a[i][j]=='C')cntc++;if (a[i][j]<='9' && a[i][j]>='2')vis[i][j]=a[i][j]-'0';else if (a[i][j]!='x')vis[i][j]=1;}}vis[ax][ay]=vis[bx][by]=vis[cx][cy]=0;if (gao(ax,ay,'a',cnta-1))cout<<"Yes"<<endl;else cout<<"No"<<endl;//for(auto it=solution.begin();it!=solution.end();++it)cout<<*it<<endl;}return 0;}


ps:
难题。大模拟。算法上就是一个搜索,考察代码能力。要稍微注意常数。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
好吧,我们这些弱校新生仔去了只能打打酱油,多喝两口水。。睡觉
0 0
原创粉丝点击