ACM暑假集训每日训练

Day1

1.棋盘问题

题意:
在一个由.# 组成的N*N的矩阵中,摆放k个棋子,问可行的摆放方案数目。(只能摆在#的位置)

样例输入:

2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1

样例输出:

2
1

:dfs
代码如下:

#include
using namespace std;
int n,k;
const int N=15;
char e[N][N]; 
int ans;
bool vis[N];
void dfs(int step,int sum)
{
	if(sum==k)
	{
		ans++;
		return;
	}

	for(int i=step+1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(!vis[j] && e[i][j]=='#')
			{
				vis[j]=1;
				dfs(i,sum+1);
				vis[j]=0; 
			}
		}
	}
	
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	while(cin>>n>>k && n!=-1 && k!=-1)
	{
		ans=0;
		memset(vis,0,sizeof(vis));
	      for(int i=1;i<=n;i++)
	      {
	      	for(int j=1;j<=n;j++)
	      	{
	      		cin>>e[i][j];
			}
		  }
		  dfs(0,0);
		  cout<<ans<<endl;
	}
	return 0;
}

2.地牢大师

题意:在三维空间中, 从 S走到E 至少要多少步(每一步只能上,下,左,右,前,后)
样例输入:

3 4 5
S....
.###.
.##..
###.#

#####
#####
##.##
##...

#####
#####
#.###
####E

1 3 3
S##
#E#
###

0 0 0

样例输出:

Escaped in 11 minute(s).
Trapped!

:bfs
代码如下

#include
using namespace std;
int l,r,c;
const int N=111;
char e[N][N][N];
bool vis[N][N][N];
int nxt[6][3]={{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};
struct node
{
	int x,y,z,step;
};
node s,f;
void init()
{
	for(int i=1;i<=l;i++)
	{
		for(int j=1;j<=r;j++)
		{
			for(int z=1;z<=c;z++)
			{
				cin>>e[i][j][z];
				if(e[i][j][z]=='S')
					s={i,j,z,0};		
		     	if(e[i][j][z]=='E')
		     	   f={i,j,z,0};
			}
		}
	}
}
bool pd(int x,int y,int z)
{
	if(x<1 || y<1 || z<1 || x>l  || y>r || z>c)
	  return 0;
	if(vis[x][y][z] || e[x][y][z]=='#')
	  return 0;
	return 1; 
}
bool flag; 
int ans;
void bfs()
{
	queue<node>q;
	q.push(s);
	while(!q.empty())
	{
		node t=q.front();
		q.pop();
		if(t.x==f.x && t.y==f.y && t.z==f.z)
		{
			flag=1;
			ans=t.step;
			return;
		}
		for(int i=0;i<=5;i++)
		{
			int tx=t.x+nxt[i][0];
			int ty=t.y+nxt[i][1];
			int tz=t.z+nxt[i][2];
			if(pd(tx,ty,tz))
			{
				vis[tx][ty][tz]=1;
				q.push({tx,ty,tz,t.step+1});
			}
		}
	 } 
	
	
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	while(cin>>l>>r>>c &&(l!=0  && r!=0 && c!=0))
	{
		memset(vis,0,sizeof(vis));
		flag=0;
		init();
		bfs();
		if(flag)
		{
			cout<<"Escaped in ";
			cout<<ans;
			cout<<" minute(s).";
		}
		else 
		  cout<<"Trapped!";
		  
		cout<<endl;
	}
	return 0;
 } 

Day2

1.Catch That Cow

题意:在一坐标轴上,给定2个点X,Y,问至少多少步可以从X走到Y,对于每一步X’:

  • X’=X+1
  • X’=X-1
  • X’=X*2

输入样例:

5 17

输出样例:

4

:bfs +vis判重
代码如下

#include
using namespace std;
int n,m;
struct node
{
	int x,step;
};
queue<node>q;
bool vis[10001];
void bfs()
{
	q.push({n,0});
	vis[n]=1;
	while(!q.empty())
	{
		node t=q.front();
		q.pop();
		if(t.x==m)
		{
			cout<<t.step;
			return;
		}
		if(t.x-1>=0 && !vis[t.x-1])
		{
			vis[t.x-1]=1;
			q.push({t.x-1,t.step+1});
		}
		if(t.x+1<=10000 && !vis[t.x+1])
		{
		    q.push({t.x+1,t.step+1});
		    vis[t.x+1]=1;
		}
		if(t.x*2<=10000 && !vis[t.x*2])
           	{q.push({t.x*2,t.step+1});
	          vis[t.x*2]=1;	
	         }
	}
}
int main()
{
	cin>>n>>m;
	bfs();
	return 0;

2.Fliptile

给定一个 M×N 的 01 矩阵。
你需要选择其中一些元素,并对选择的元素进行翻转操作。
翻转操作是指将所选元素以及与其上下左右相邻的元素(如果有)进行翻转(0 变 1,1 变 0)。
我们希望最终矩阵变为一个全 0 矩阵,并且选择进行翻转操作的元素数量尽可能少。
输出最佳翻转方案。

输入格式
第一行包含整数 M,N。
接下来 M 行,每行包含 N 个整数,每个整数为 0 或 1。

输出格式
共 M 行,每行包含 N 个整数,其中第 i 行第 j 列的整数,表示第 i 行第 j 列元素的翻转次数。

如果翻转操作次数最少的操作方案不唯一,则输出字典序最小的方案。
如果不存在合理方案,则输出 IMPOSSIBLE。

数据范围
1≤M,N≤15

:先枚举第一行的翻转方式,再从第二行开始,根据上一行的状态进行翻转
代码如下

#include
using namespace std;
const int N=20;
int e[N][N];
int n,m;
int temp[N][N];
int a[N][N],ta[N][N];
bool flag=0;
int nxt[5][2]={{0,0},{1,0},{-1,0},{0,-1},{0,1}};
void trans(int x,int y)
{
	for(int i=0;i<=4;i++)
	{
		int tx=x+nxt[i][0];
		int ty=y+nxt[i][1];
		if(tx<1 || ty<1 || tx>n || ty>m)
		  continue;
		temp[tx][ty]^=1;
	}
}
int ans;
int minn=1000001;
bool check()
{
	for(int i=1;i<=n;i++)
	{
	   for(int j=1;j<=m;j++)
	   {
	   	   if(temp[i][j])
	   	     return 0;
		} 
	}
	return 1;
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>e[i][j];
		}
	}
	for(int i=0;i<(1<<m);i++)
	{
	    ans=0;
		int k=i;
		memcpy(temp,e,sizeof(e));
		memset(ta,0,sizeof(ta));
		for(int j=0;j<m;j++)
		{	
			if((k>>j)&1)
			{
				trans(1,j+1);
				ans++;
				ta[1][j+1]++;
			}	
		}
		
		for(int i=2;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
		    {
			  if(temp[i-1][j]==1)
		      {
				trans(i,j);
				 ans++;
				 ta[i][j]++;
			  }
		    }
		}

		if(check() && minn>ans)
		{
			minn=ans;
			flag=1;
			memcpy(a,ta,sizeof(ta));
		}				
	}
	if(flag)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				cout<<a[i][j]<<" ";
			}
			cout<<endl;
		}	
	}
	else 
	  cout<<"IMPOSSIBLE";
	
}

Day3

1.找倍数

描述
给定一个正整数 n,请你找到一个它的非零倍数 m。
要求 m 中只包含数字 0 或 1,并且总位数不超过 100 位。

输入格式
输入包含多组测试数据。
每组数据占一行,包含一个正整数 n。
当输入 n=0 时,表示输入结束。

输出格式
每组数据输出一行 m。
如果方案不唯一,则输出任意合理方案均可。

数据范围
1≤n≤200

输入样例:

2
6
19
0

输出样例:

10
100100100100100100
111111111111111111

:既然ans是关于m的倍数的‘01’串,那么每次对下一位进行bfs(0)或者bfs(1)
代码如下:

#include
using namespace std;
int n;
struct node 
{
	string s;
	int x;
};
void solve()
{
	queue<node>q;
	q.push({"1",1});
	while(!q.empty())
	{
		node t=q.front();
		q.pop();
		if(t.x%n==0)
		{
			cout<<t.s;
			return;
		}
		int tx;
		string ts;
		tx=(t.x*10)%n;
		ts=t.s+"0";
		q.push({ts,tx});
		
		tx=(t.x*10+1)%n;
		ts=t.s+"1";
		q.push({ts,tx}); 
	}
}
int main()
{
	while(cin>>n && n)
	{
		solve();
		cout<<endl;
		
	}
	return 0;
}

2.质数路径

题目:
给定两个四位质数 A 和 B,你需要通过最少的操作次数将 A 变为 B。
每次操作只能改变当前数的其中一位数字,并且每次操作过后,当前数必须仍然是一个质数。
例如:将 1033 变为 8179,最少需要进行 6 次操作,具体操作为:

1033 -> 1733 -> 3733 -> 3739 -> 3779 -> 8779 -> 8179

请计算并输出所需要的最少操作次数。

输入格式
第一行包含整数 T,表示共有 T 组测试数据。
每组数据占一行,包含两个四位质数 A 和 B。

输出格式
每组数据输出一行答案,表示所需最少操作次数。
如果无法做到,则输出Impossible
经实际测试,不存在无解情况,特此声明。
数据范围
1≤T≤100。
1000≤A,B≤9999,
保证 A 和 B 都是质数。
输入样例

3
1033 8179
1373 8017
1033 1033

输出样例:

6
7
0

:bfs + vis判重+pd(质数判断)
代码如下:

#include
using namespace std;
int t;
int a,b;
bool Pd[12011];
int p[2000]={1009 ,1013 ,1019 ,1021 ,1031 ,1033 ,1039 ,1049 ,1051 ,1061 ,1063 ,1069 ,1087 ,1091 ,1093 ,1097 ,1103 ,1109 ,1117 ,1123 ,1129 ,1151 ,1153 ,1163 ,1171 ,1181 ,1187 ,1193 ,1201 ,1213 ,1217 ,1223 ,1229 ,1231 ,1237 ,1249 ,1259 ,1277 ,1279 ,1283 ,1289 ,1291 ,1297 ,1301 ,1303 ,1307 ,1319 ,1321 ,1327 ,1361 ,1367 ,1373 ,1381 ,1399 ,1409 ,1423 ,1427 ,1429 ,1433 ,1439 ,1447 ,1451 ,1453 ,1459 ,1471 ,1481 ,1483 ,1487 ,1489 ,1493 ,1499 ,1511 ,1523 ,1531 ,1543 ,1549 ,1553 ,1559 ,1567 ,1571 ,1579 ,1583 ,1597 ,1601 ,1607 ,1609 ,1613 ,1619 ,1621 ,1627 ,1637 ,1657 ,1663 ,1667 ,1669 ,1693 ,1697 ,1699 ,1709 ,1721 ,1723 ,1733 ,1741 ,1747 ,1753 ,1759 ,1777 ,1783 ,1787 ,1789 ,1801 ,1811 ,1823 ,1831 ,1847 ,1861 ,1867 ,1871 ,1873 ,1877 ,1879 ,1889 ,1901 ,1907 ,1913 ,1931 ,1933 ,1949 ,1951 ,1973 ,1979 ,1987 ,1993 ,1997 ,1999 ,2003 ,2011 ,2017 ,2027 ,2029 ,2039 ,2053 ,2063 ,2069 ,2081 ,2083 ,2087 ,2089 ,2099 ,2111 ,2113 ,2129 ,2131 ,2137 ,2141 ,2143 ,2153 ,2161 ,2179 ,2203 ,2207 ,2213 ,2221 ,2237 ,2239 ,2243 ,2251 ,2267 ,2269 ,2273 ,2281 ,2287 ,2293 ,2297 ,2309 ,2311 ,2333 ,2339 ,2341 ,2347 ,2351 ,2357 ,2371 ,2377 ,2381 ,2383 ,2389 ,2393 ,2399 ,2411 ,2417 ,2423 ,2437 ,2441 ,2447 ,2459 ,2467 ,2473 ,2477 ,2503 ,2521 ,2531 ,2539 ,2543 ,2549 ,2551 ,2557 ,2579 ,2591 ,2593 ,2609 ,2617 ,2621 ,2633 ,2647 ,2657 ,2659 ,2663 ,2671 ,2677 ,2683 ,2687 ,2689 ,2693 ,2699 ,2707 ,2711 ,2713 ,2719 ,2729 ,2731 ,2741 ,2749 ,2753 ,2767 ,2777 ,2789 ,2791 ,2797 ,2801 ,2803 ,2819 ,2833 ,2837 ,2843 ,2851 ,2857 ,2861 ,2879 ,2887 ,2897 ,2903 ,2909 ,2917 ,2927 ,2939 ,2953 ,2957 ,2963 ,2969 ,2971 ,2999 ,3001 ,3011 ,3019 ,3023 ,3037 ,3041 ,3049 ,3061 ,3067 ,3079 ,3083 ,3089 ,3109 ,3119 ,3121 ,3137 ,3163 ,3167 ,3169 ,3181 ,3187 ,3191 ,3203 ,3209 ,3217 ,3221 ,3229 ,3251 ,3253 ,3257 ,3259 ,3271 ,3299 ,3301 ,3307 ,3313 ,3319 ,3323 ,3329 ,3331 ,3343 ,3347 ,3359 ,3361 ,3371 ,3373 ,3389 ,3391 ,3407 ,3413 ,3433 ,3449 ,3457 ,3461 ,3463 ,3467 ,3469 ,3491 ,3499 ,3511 ,3517 ,3527 ,3529 ,3533 ,3539 ,3541 ,3547 ,3557 ,3559 ,3571 ,3581 ,3583 ,3593 ,3607 ,3613 ,3617 ,3623 ,3631 ,3637 ,3643 ,3659 ,3671 ,3673 ,3677 ,3691 ,3697 ,3701 ,3709 ,3719 ,3727 ,3733 ,3739 ,3761 ,3767 ,3769 ,3779 ,3793 ,3797 ,3803 ,3821 ,3823 ,3833 ,3847 ,3851 ,3853 ,3863 ,3877 ,3881 ,3889 ,3907 ,3911 ,3917 ,3919 ,3923 ,3929 ,3931 ,3943 ,3947 ,3967 ,3989 ,4001 ,4003 ,4007 ,4013 ,4019 ,4021 ,4027 ,4049 ,4051 ,4057 ,4073 ,4079 ,4091 ,4093 ,4099 ,4111 ,4127 ,4129 ,4133 ,4139 ,4153 ,4157 ,4159 ,4177 ,4201 ,4211 ,4217 ,4219 ,4229 ,4231 ,4241 ,4243 ,4253 ,4259 ,4261 ,4271 ,4273 ,4283 ,4289 ,4297 ,4327 ,4337 ,4339 ,4349 ,4357 ,4363 ,4373 ,4391 ,4397 ,4409 ,4421 ,4423 ,4441 ,4447 ,4451 ,4457 ,4463 ,4481 ,4483 ,4493 ,4507 ,4513 ,4517 ,4519 ,4523 ,4547 ,4549 ,4561 ,4567 ,4583 ,4591 ,4597 ,4603 ,4621 ,4637 ,4639 ,4643 ,4649 ,4651 ,4657 ,4663 ,4673 ,4679 ,4691 ,4703 ,4721 ,4723 ,4729 ,4733 ,4751 ,4759 ,4783 ,4787 ,4789 ,4793 ,4799 ,4801 ,4813 ,4817 ,4831 ,4861 ,4871 ,4877 ,4889 ,4903 ,4909 ,4919 ,4931 ,4933 ,4937 ,4943 ,4951 ,4957 ,4967 ,4969 ,4973 ,4987 ,4993 ,4999 ,5003 ,5009 ,5011 ,5021 ,5023 ,5039 ,5051 ,5059 ,5077 ,5081 ,5087 ,5099 ,5101 ,5107 ,5113 ,5119 ,5147 ,5153 ,5167 ,5171 ,5179 ,5189 ,5197 ,5209 ,5227 ,5231 ,5233 ,5237 ,5261 ,5273 ,5279 ,5281 ,5297 ,5303 ,5309 ,5323 ,5333 ,5347 ,5351 ,5381 ,5387 ,5393 ,5399 ,5407 ,5413 ,5417 ,5419 ,5431 ,5437 ,5441 ,5443 ,5449 ,5471 ,5477 ,5479 ,5483 ,5501 ,5503 ,5507 ,5519 ,5521 ,5527 ,5531 ,5557 ,5563 ,5569 ,5573 ,5581 ,5591 ,5623 ,5639 ,5641 ,5647 ,5651 ,5653 ,5657 ,5659 ,5669 ,5683 ,5689 ,5693 ,5701 ,5711 ,5717 ,5737 ,5741 ,5743 ,5749 ,5779 ,5783 ,5791 ,5801 ,5807 ,5813 ,5821 ,5827 ,5839 ,5843 ,5849 ,5851 ,5857 ,5861 ,5867 ,5869 ,5879 ,5881 ,5897 ,5903 ,5923 ,5927 ,5939 ,5953 ,5981 ,5987 ,6007 ,6011 ,6029 ,6037 ,6043 ,6047 ,6053 ,6067 ,6073 ,6079 ,6089 ,6091 ,6101 ,6113 ,6121 ,6131 ,6133 ,6143 ,6151 ,6163 ,6173 ,6197 ,6199 ,6203 ,6211 ,6217 ,6221 ,6229 ,6247 ,6257 ,6263 ,6269 ,6271 ,6277 ,6287 ,6299 ,6301 ,6311 ,6317 ,6323 ,6329 ,6337 ,6343 ,6353 ,6359 ,6361 ,6367 ,6373 ,6379 ,6389 ,6397 ,6421 ,6427 ,6449 ,6451 ,6469 ,6473 ,6481 ,6491 ,6521 ,6529 ,6547 ,6551 ,6553 ,6563 ,6569 ,6571 ,6577 ,6581 ,6599 ,6607 ,6619 ,6637 ,6653 ,6659 ,6661 ,6673 ,6679 ,6689 ,6691 ,6701 ,6703 ,6709 ,6719 ,6733 ,6737 ,6761 ,6763 ,6779 ,6781 ,6791 ,6793 ,6803 ,6823 ,6827 ,6829 ,6833 ,6841 ,6857 ,6863 ,6869 ,6871 ,6883 ,6899 ,6907 ,6911 ,6917 ,6947 ,6949 ,6959 ,6961 ,6967 ,6971 ,6977 ,6983 ,6991 ,6997 ,7001 ,7013 ,7019 ,7027 ,7039 ,7043 ,7057 ,7069 ,7079 ,7103 ,7109 ,7121 ,7127 ,7129 ,7151 ,7159 ,7177 ,7187 ,7193 ,7207 ,7211 ,7213 ,7219 ,7229 ,7237 ,7243 ,7247 ,7253 ,7283 ,7297 ,7307 ,7309 ,7321 ,7331 ,7333 ,7349 ,7351 ,7369 ,7393 ,7411 ,7417 ,7433 ,7451 ,7457 ,7459 ,7477 ,7481 ,7487 ,7489 ,7499 ,7507 ,7517 ,7523 ,7529 ,7537 ,7541 ,7547 ,7549 ,7559 ,7561 ,7573 ,7577 ,7583 ,7589 ,7591 ,7603 ,7607 ,7621 ,7639 ,7643 ,7649 ,7669 ,7673 ,7681 ,7687 ,7691 ,7699 ,7703 ,7717 ,7723 ,7727 ,7741 ,7753 ,7757 ,7759 ,7789 ,7793 ,7817 ,7823 ,7829 ,7841 ,7853 ,7867 ,7873 ,7877 ,7879 ,7883 ,7901 ,7907 ,7919 ,7927 ,7933 ,7937 ,7949 ,7951 ,7963 ,7993 ,8009 ,8011 ,8017 ,8039 ,8053 ,8059 ,8069 ,8081 ,8087 ,8089 ,8093 ,8101 ,8111 ,8117 ,8123 ,8147 ,8161 ,8167 ,8171 ,8179 ,8191 ,8209 ,8219 ,8221 ,8231 ,8233 ,8237 ,8243 ,8263 ,8269 ,8273 ,8287 ,8291 ,8293 ,8297 ,8311 ,8317 ,8329 ,8353 ,8363 ,8369 ,8377 ,8387 ,8389 ,8419 ,8423 ,8429 ,8431 ,8443 ,8447 ,8461 ,8467 ,8501 ,8513 ,8521 ,8527 ,8537 ,8539 ,8543 ,8563 ,8573 ,8581 ,8597 ,8599 ,8609 ,8623 ,8627 ,8629 ,8641 ,8647 ,8663 ,8669 ,8677 ,8681 ,8689 ,8693 ,8699 ,8707 ,8713 ,8719 ,8731 ,8737 ,8741 ,8747 ,8753 ,8761 ,8779 ,8783 ,8803 ,8807 ,8819 ,8821 ,8831 ,8837 ,8839 ,8849 ,8861 ,8863 ,8867 ,8887 ,8893 ,8923 ,8929 ,8933 ,8941 ,8951 ,8963 ,8969 ,8971 ,8999 ,9001 ,9007 ,9011 ,9013 ,9029 ,9041 ,9043 ,9049 ,9059 ,9067 ,9091 ,9103 ,9109 ,9127 ,9133 ,9137 ,9151 ,9157 ,9161 ,9173 ,9181 ,9187 ,9199 ,9203 ,9209 ,9221 ,9227 ,9239 ,9241 ,9257 ,9277 ,9281 ,9283 ,9293 ,9311 ,9319 ,9323 ,9337 ,9341 ,9343 ,9349 ,9371 ,9377 ,9391 ,9397 ,9403 ,9413 ,9419 ,9421 ,9431 ,9433 ,9437 ,9439 ,9461 ,9463 ,9467 ,9473 ,9479 ,9491 ,9497 ,9511 ,9521 ,9533 ,9539 ,9547 ,9551 ,9587 ,9601 ,9613 ,9619 ,9623 ,9629 ,9631 ,9643 ,9649 ,9661 ,9677 ,9679 ,9689 ,9697 ,9719 ,9721 ,9733 ,9739 ,9743 ,9749 ,9767 ,9769 ,9781 ,9787 ,9791 ,9803 ,9811 ,9817 ,9829 ,9833 ,9839 ,9851 ,9857 ,9859 ,9871 ,9883 ,9887 ,9901 ,9907 ,9923 ,9929 ,9931 ,9941 ,9949 ,9967 ,9973 };
bool vis[10011];
bool flag;
int ans;
void pd()
{
    for(int i=0;i<2000;i++)
    {
    	Pd[p[i]]=1;
	}
}
struct node
{
	int x,step;
};	
int cnt;
int temp[5];
int work(int x,int i,int j)
{
	cnt=0;
	while(x)
	{
		temp[++cnt]=x%10;
		x/=10;
	}
	temp[i]=j;
	return temp[1]+temp[2]*10+temp[3]*100+temp[4]*1000;
}
void bfs()
{
	queue<node>q;
	q.push({a,0});
	while(!q.empty())
	{
		node t=q.front();
		q.pop();
		if(t.x==b)
		{
			flag=1;
			ans=t.step;
			return;
		}
		for(int i=1;i<=4;i++)
		{
			for(int j=0;j<=9;j++)
			{
				if(i==1 && j==0)
				  continue;
				int now=work(t.x,i,j);
				if(Pd[now] && !vis[now])
				{
					vis[now]=1;
					q.push({now,t.step+1});
				}
			}
		}
	}

}
int main()
{
	cin>>t;
	pd();
	while(t--)
	{
		flag=0;
		memset(vis,0,sizeof(vis));
		
		cin>>a>>b; 
		bfs();
		if(flag)
		{
			cout<<ans;
		}
		else 
		  cout<<"IMPOSSIBLE";
		cout<<endl;
	}
	
}

Day4

1.洗牌

描述:
给定两叠纸牌 S1 和 S2,每叠恰好有 C 张牌。
每张牌的尺寸大小都完全相同,但是颜色可能不同。
下面介绍洗牌规则。
不妨设 S1 中纸牌从上到下编号依次为 a1,a2,…,aC,S2 中纸牌从上到下编号依次为 b1,b2,…,bC。
洗牌就是将这两叠牌交错堆叠在一起,形成一个拥有 2C 张牌的新牌堆 S12。
新牌堆中的牌由上至下依次为 a1,b1,a2,b2,…,aC,bC。
可参考下图:ACM暑假集训每日训练_第1张图片
然后,将牌堆从中间一分为二,下半部分是新的 S1,上半部分是新的 S2。

这样就可以继续进行洗牌操作获得新的 S12 了。

给定 S1 和 S2,请问至少需要进行多少轮洗牌操作方可获得指定牌堆 S12。

输入格式
第一行包含一个整数 T,表示共有 T 组测试数据。

每组数据第一行包含一个整数 C。

第二行包含一个长度为 C 的由大写字母构成的字符串,其中第 i 个字母表示初始 S1 中由底向上第 i 张牌的颜色。

第三行包含一个长度为 C 的由大写字母构成的字符串,其中第 i 个字母表示初始 S2 中由底向上第 i 张牌的颜色。

第四行包含一个长度为 2C 的由大写字母构成的字符串,其中第 i 个字母表示目标 S12 中由底向上第 i 张牌的颜色。

输出格式
共 T 行,每行输出一组数据的结果,首先输出组别编号 i(从 1 开始),然后输出所需要的最少洗牌次数。如果无法通过洗牌获得目标牌堆,则输出 −1。

数据范围
1≤T≤1000,
1≤C≤100。
卡牌最多有 8 种颜色,用大写字母 A∼H 表示,所以输入字符串中不会出现其他大写字母。
输入样例

2
4
AHAH
HAHA
HHAAAAHH
3
CDE
CDE
EEDDCC

输出样例:

1 2
2 -1

:…用手

#include
using namespace std;
string s1,s2,s;
int t,n;
bool flag;
int ans;
void solve(string x,string y,int step)
{
	if(step>2*n)
	   return;
	if(flag)
	  return;
	
	string t1="",t2="";
	int i;
	for(i=0;i<n/2;i++)
	{
	   t1+=y[i];
	   t1+=x[i];	
	} 
	if(n%2)
	{
		t1+=y[i];
		t2+=x[i];
		i++;
	}
	for(i;i<n;i++)
	{
		t2+=y[i];
		t2+=x[i];
	}
	if(t1+t2==s)
	{
		flag=1;
		ans=step+1;
		return;
	}
//	cout<
	solve(t1,t2,step+1);
}
int main()
{
	cin>>t;
	for(int i=1;i<=t;i++)
	{
		cin>>n;
		flag=0;
		cin>>s1>>s2>>s;
		solve(s1,s2,0);
		cout<<i<<" ";
		if(flag)
		  cout<<ans;
		else 
		  cout<<-1;
		cout<<endl;
	}
}

2.罐子

描述:
给你两个罐子,容积分别为 A 升和 B 升。
现在,你可以进行如下三种操作:

FILL(i),将罐子 i(1≤i≤2)灌满水。
DROP(i),将罐子 i(1≤i≤2)清空。
POUR(i,j),将罐子 i 中的水倒向罐子 j,直到罐子 i 空了或罐子 j 满了为止。
请问,至少多少次操作后,可以使得其中一个罐子里恰好有 C 升水。

输入格式
共一行,三个整数 A,B,C。

输出格式
如果无解,则输出一行 impossible 即可。
否则,第一行输出一个整数,表示最少操作次数。
随后按顺序每行输出一个操作指令,格式参考题面。

数据范围
1≤A,B,C≤100,
C≤max(A,B)。
输入样例:

3 5 4

输出样例:

6

:bfs
代码如下:

#include
using namespace std;
int a,b,c;
string op[6]={"FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};

struct node
{
	int v1,v2;
	string s;
};
bool flag;
node ans;
map<pair<int,int>,int>e;
queue<node>q;
void solve()
{
	q.push({0,0,""});
	e[{0,0}]=1;
	while(!q.empty())
	{
		node t=q.front();
		q.pop();
		if(t.v1==c || t.v2==c)
		{
			flag=1;
			ans=t;
			return;
		}
		int v1=t.v1,v2=t.v2;
		
		if(!e[{a,v2}])
		{
			e[{a,v2}]=1;
		   q.push({a,v2,t.s+"1"});
		}
		if(!e[{v1,b}])
		{
			e[{v1,b}]=1;
			q.push({v1,b,t.s+"2"});
		}
		if(!e[{0,v2}])
		{
			e[{0,v2}]=1;
			q.push({0,v2,t.s+"3"});
		}
		if(!e[{v1,0}])
		{
			e[{v1,0}]=1;
			q.push({v1,0,t.s+"4"});
		}
		int temp=min(b,v1+v2);
		v1=v1-(temp-v2);
		if(!e[{v1,temp}])
		{
			e[{v1,temp}]=1;
			q.push({v1,temp,t.s+"5"});
		}
		v1=t.v1;
		v2=t.v2;
		temp=min(a,v1+v2);
		v2=v2-(temp-v1);
		
		if(!e[{temp,v2}])
		{
			e[{temp,v2}]=1;
			q.push({temp,v2,t.s+"6"});
		}	
	}
	
}
int main()
{
   cin>>a>>b>>c;
   solve();
   if(flag)
   {
   	cout<<ans.s.length()<<endl;
   	
   	  for(int i=0;i<ans.s.length();i++)
   	  {
   	  	char c=ans.s[i];
   	  	int j=c-'0'-1;
   	  	cout<<op[j]<<endl;
	  }
   }
   else 
     cout<<"impossible";
   return 0;	
}

Day5

1.迷宫问题

描述
定义一个二维数组:
int maze[5][5] = {

0, 1, 0, 0, 0,

0, 1, 0, 1, 0,

0, 0, 0, 0, 0,

0, 1, 1, 1, 0,

0, 0, 0, 1, 0,

};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
样例输入:

0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

样例输出:

(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)

:用手
代码如下

#include
using namespace std;
int e[7][7];
int nxt[4][2]={{-1,0},{1,0},{0,1},{0,-1}};

bool vis[7][7];
struct node
{
	int x ,y;
	string s;
};
queue<node>q; 

string ans;
void bfs()
{
	q.push({1,1,"(0, 0)"});
	while(!q.empty())
	{
		 node t=q.front();
		 q.pop();
		 if(t.x==5 && t.y==5)
		 {
		 	ans=t.s;

		 	return ;
		 } 
		 for(int i=0;i<=3;i++)
		 {
		 	int tx=t.x+nxt[i][0];
		 	int ty=t.y+nxt[i][1];
		 	if(tx<1 || ty<1 || tx>5 || ty>5)
		 	  continue;
		 	if(!vis[tx][ty] && e[tx][ty]==0)
		 	{
		 	  vis[tx][ty]=1;
		 	  tx--;
		 	  ty--;
		 	  string ts=t.s;
		 	  ts+='\n';
		 	  ts+="(";
		 	  ts+=tx+'0';
		 	  ts+=", ";
		 	  ts+=ty+'0';
		 	  ts+=")";
		 	  tx++;
		 	  ty++;
			   q.push({tx,ty,ts});	
			}
		 	
		 }
	}
}
int main()
{
	for(int i=1;i<=5;i++)
	{
		for(int j=1;j<=5;j++)
		  cin>>e[i][j];
	}
	bfs();	
	cout<<ans;
	return 0;
 } 

2.石油储备

描述:
一片土地可以看作是一个 n 行 m 列的方格矩阵。
其中一些方格藏有石油,用 @ 表示,其余方格没有石油,用 * 表示。
每个方格都与其上、下、左、右、左上、右上、左下、右下八个方格视为相邻。
如果两个藏有石油的方格相邻,则它们被认为是处于同一片油田,否则它们被认为是处于不同油田。
请问,该土地中共有多少片油田。

输入格式
输入包含多组测试数据。
每组数据第一行包含两个整数 n,m。
接下来 n 行,包含一个 n 行 m 列的字符矩阵,表示土地情况。
当输入一行 0 0 时,表示输入结束。

输出格式
每组数据输出一行,一个整数,表示油田数量。

数据范围
最多包含 100 组数据。
1≤n,m≤100。

样例输入

1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5 
****@
*@@*@
*@**@
@@@*@
@@**@
0 0

样例输出:

0
1
2
2

1:用手
代码如下:

#include
using namespace std;
int n,m;
const int N=111;
char e[N][N];
int cnt=0;
bool vis[N][N];
int nxt[8][2]={{-1,-1},{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1}};
struct node
{
	int x,y;
};
queue<node>q;
void clear()
{
	while(!q.empty())
	{
		q.pop();
	}
}
void bfs(int x,int y)
{
	clear();
	q.push({x,y});
	while(!q.empty())
	{
		node t=q.front();
		q.pop();
		for(int i=0;i<=7;i++)
		{
			int tx=t.x+nxt[i][0];
			int ty=t.y+nxt[i][1];
			if(tx<1 || ty<1 || tx>n || ty>m)
			  continue;
			if(!vis[tx][ty] && e[tx][ty]=='@')
			{
				vis[tx][ty]=1;
				q.push({tx,ty});
			}
		}
		
	}
}
int main()
{
	while(cin>>n>>m && n!=0 && m!=0)
	{
		memset(vis,0,sizeof(vis));
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				cin>>e[i][j];
			}
		}
		cnt=0;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				
				if(e[i][j]=='@' && vis[i][j]==0)
				{
					cnt++;
					vis[i][j]=1; 
					bfs(i,j);
				}
			}
		}
		
		cout<<cnt<<endl;
	}
}

Day6

1.非常可乐

描述:
大家一定觉的运动以后喝可乐是一件很惬意的事情,但是 seeyou 却不这么认为。
因为每次当 seeyou 买了可乐以后,阿牛就要求和 seeyou 一起分享这一瓶可乐,而且一定要喝的和 seeyou 一样多。
但 seeyou 的手中只有两个杯子,它们的容量分别是 N 毫升和 M 毫升。
可乐的体积为 S (S<101)毫升 (正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 S=N+M,101>S>0,N>0,M>0) 。
聪明的 ACMER 你们说他们能平分吗?
如果能请输出倒可乐的最少的次数,如果不能输出 NO
输入格式
输入包含多组测试数据。
每组数据一行,三个整数 S,N,M。
当输入一行为 0 0 0 时,表示输入结束。
输出格式
每组数据输出一行结果,如果能够平分,则输出倒可乐的最少的次数,否则输出 NO。
数据范围
S=N+M,101>S>0,N>0,M>0)
输入样例:

7 4 3
4 1 3
0 0 0

输出样例:

NO
3

:和昨天的倒水问题一样的
代码如下

#include
using namespace std;
const int N=111;
struct node
{
	int v1,v2,v3,step;
};
bool flag;
int s,n,m;
int ans;
bool vis[N][N][N];

void solve()
{
	queue<node>q;
	q.push({s,0,0,0});
	while(!q.empty())
	{
		node t=q.front();
		q.pop();
		if((t.v1==t.v2 && t.v1+t.v2==s)||( t.v2==t.v3 && t.v2+t.v3==s)||(t.v1+t.v3==s  && t.v1==t.v3))
		{
		    flag=1;
		    ans=t.step;
		    return;
		} 
		int tt=t.step+1;
		int t1;                   // v1->v2
		t1=min(n,t.v2+t.v1);
		if(!vis[t.v1-(t1-t.v2)][t1][t.v3])
		{
		  vis[t.v1-(t1-t.v2)][t1][t.v3]=1;
		  q.push({t.v1-(t1-t.v2),t1,t.v3,tt});
	    }
		
		int t2;                  //v1->v3
		t2=min(m,t.v3+t.v1);
		if(!vis[t.v1-(t2-t.v3)][t.v2][t2])
		{
			vis[t.v1-(t2-t.v3)][t.v2][t2]=1;
			q.push({t.v1-(t2-t.v3),t.v2,t2,tt});
		}
		
		int t3;    // v2->v1
		t3=min(t.v1+t.v2,s);
		if(!vis[t3][t.v2-(t3-t.v1)][t.v3])
		{
			vis[t3][t.v2-(t3-t.v1)][t.v3]=1;
			q.push({t3,t.v2-(t3-t.v1),t.v3,tt});
		}
		int t4; //v2->v3
        t4=min(t.v2+t.v3,m);
		if(!vis[t.v1][t.v2-(t4-t.v3)][t4])
		{
		   vis[t.v1][t.v2-(t4-t.v3)][t4]=1;
		   q.push({t.v1,t.v2-(t4-t.v3),t4,tt});	
		}
		int t5; // v3->v1
		t5=min(s,t.v1+t.v3);
		if(!vis[t5][t.v2][t.v3-(t5-t.v1)])
		{
			vis[t5][t.v2][t.v3-(t5-t.v1)]=1;
			q.push({t5,t.v2,t.v3-(t5-t.v1),tt});
		}
		int t6;  // v3->v2;
		t6=min(n,t.v3+t.v2);
		if(!vis[t.v1][t6][t.v3-(t6-t.v2)])
		{
			vis[t.v1][t6][t.v3-(t6-t.v2)];
			q.push({t.v1,t6,t.v3-(t6-t.v2),tt});
		}
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	while(cin>>s>>n>>m && (s!=0 && n!=0 && m!=0))
	{
		memset(vis,0,sizeof(vis));
		flag=0;
		if(s%2)
		  cout<<"NO";
		else
		{
	     solve();
	     if(flag)
	       cout<<ans;
	     else 
	       cout<<"NO";
	    }
	    cout<<endl;
	}
}

2.找路

描述
给定一个 n 行 m 列的方格矩阵。
其中有些方格是空地(可以进入),有些方格是餐厅(可以进入),有些方格是障碍(不可进入)。
开始时,小 Y 和小 M 各自位于一个空地方格中。
每个人都可以沿上下左右四个方向进行移动,移动一格距离需要花费 11 分钟时间。
他们希望选择一家餐厅进行聚餐,要求两人从各自出发点到达该餐厅所花费的时间之和尽可能小。
输出这个最小时间和。

输入格式
输入包含多组测试数据。
每组数据第一行包含两个整数 n,m。
接下来 n 行,包含一个 n×m 的字符矩阵。
矩阵中只包含以下五种字符:

# 表示障碍方格。
. 表示空地方格。
Y 表示小 Y 所在的空地方格,有且仅有一个。
M 表示小 M 所在的空地方格,有且仅有一个。
@ 表示餐厅。
输出格式
每组数据输出一行答案,表示最小时间和。
保证一定有解。
数据范围
最多包含 100 组数据。
2≤n,m≤200。
输入样例

4 4
Y.#@
....
.#..
@..M
4 4
Y.#@
....
.#..
@#.M
5 5
Y..@.
.#...
.#...
@..M.
#...#

输出样例:

66
88
66

:和前几天的一道题差不多

#include
using namespace std;
const int N=211;
int t1[N][N],t2[N][N];
char e[N][N];
int n,m;

struct node
{
	int x,y;
};
node Y,M;
int cnt;
int nxt[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
bool vis[N][N];

void solve(int T[N][N],node X)
{
	queue<node>q;
	q.push({X.x,X.y});
	T[X.x][X.y]=0;
	memset(vis,0,sizeof(vis));
	vis[X.x][X.y]=1;
	while(!q.empty())
	{
		node t=q.front();
		q.pop();
		for(int i=0;i<=3;i++)
		{
			int tx=t.x+nxt[i][0];
			int ty=t.y+nxt[i][1];
			if(tx<1 || ty<1 || tx>n || ty>m)
			  continue;
			if(e[tx][ty]=='#')
			  continue;
			if(vis[tx][ty])
			  continue;
			
				T[tx][ty]=T[t.x][t.y]+1;
				q.push({tx,ty});
				vis[tx][ty]=1;
		}
		
	}
}


void init()
{
	cnt=0;
	memset(t1,-1,sizeof(t1));
	memset(t2,-1,sizeof(t2));
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		 {
		   cin>>e[i][j];
		   char t=e[i][j];
		   if(t=='Y')
		     Y={i,j};
		    if(t=='M')
		      M={i,j};
	     }
	}
}
int ans;
int main()
{
	while(cin>>n>>m)
	{
	   init();
	   ans=1000000001;
	   solve(t1,Y);
	   solve(t2,M);
	   for(int i=1;i<=n;i++)
	   {
	   	for(int j=1;j<=m;j++)
	   	{
	   		if(e[i][j]=='@' &&t1[i][j]!=-1 )
	   		{
	   		   	ans=min(ans,t1[i][j]+t2[i][j]);
			 }
		   }
	   }
	   cout<<ans*11<<endl;
	}
	return 0;
	
 } 

recently:
请添加图片描述
请添加图片描述
ACM暑假集训每日训练_第2张图片
and
ACM暑假集训每日训练_第3张图片

你可能感兴趣的:(算法,c++,算法,学习)