幻象迷宫
解题思路: 搜素题型,但是还是有细节需要优化,理解假如能走到之前走到过的环境相同的点
代码: 【借鉴】
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define MEM(arr,num) memset(arr,num,sizeof(arr))
#define FOR(i,l,r) for(int i(l);i < r;++i)
#define SIZE 1511
using namespace std;
char board[SIZE][SIZE];
bool map1[SIZE * 2][SIZE * 2], map2[SIZE][SIZE];
//map1表示有无走到过这个点,map2表示有无走到过映射点
int n, m, dn, dm;
bool dfs(int x,int y)
{
if(x == -1)
{
if(dfs(dn - 1, y))return true;
return false;
}
if(x == dn)
{
if(dfs(0, y))return true;
return false;
}
if(y == -1)
{
if(dfs(x, dm - 1))return true;
return false;
}
if(y == dm)
{
if(dfs(x, 0))return true;
return false;
}//上面四个if表示是否到边界,是就传送
if(map1[x][y] || board[x % n][y % m] == '#')
{
return false;
}//判断能不能走
if(map2[x % n][y % m])
{
return true;
}//判断这有没有走到这个点的映射
map1[x][y] = true;
map2[x % n][y % m] = true;
//记录
if(dfs(x + 1, y))return true;
if(dfs(x - 1, y))return true;
if(dfs(x, y + 1))return true;
if(dfs(x, y - 1))return true;
//遍历
return false;
}
int main()
{
while(cin >> n >> m)
{
dn = n * 2;
dm = m * 2;
int sx, sy;
FOR(i, 0, n)
{
FOR(j, 0, m)
{
cin >> board[i][j];
if(board[i][j] == 'S')
{
sx = i;
sy = j;
}
}
}//输入+找起点
MEM(map1, 0);
MEM(map2, 0);
if(dfs(sx, sy)) printf("Yes\n");
else printf("No\n");
}
return 0;
}
解题思路:
后续:
链接: 传送门
创意吃鱼法
解题思路: 题型是dp+预处理,理解dp方程f[i][j]=min(f[i-1][j-1],min(s1[i][j-1],s2[i-1][j]))+1
代码: 【借鉴】
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<string>
#include<map>
typedef long long ll;
using namespace std;
int n,m,ans;
int a[2509][2509],f[2509][2509],s1[2509][2509],s2[2509][2509];//s1为横向,s2为纵向
int main()
{
cin>>n>>m;
//第一遍左上——右下
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
if(!a[i][j])
{
s1[i][j]=s1[i][j-1]+1;
s2[i][j]=s2[i-1][j]+1;
}
if(a[i][j])
f[i][j]=min(f[i-1][j-1],min(s1[i][j-1],s2[i-1][j]))+1;
ans=max(ans,f[i][j]);
}
//第二遍右上——左下
memset(f,0,sizeof(f));
memset(s1,0,sizeof(s1));//数组置0
memset(s2,0,sizeof(s2));
for(int i=1;i<=n;i++)
for(int j=m;j>=1;j--)
{
if(!a[i][j])
{
s1[i][j]=s1[i][j+1]+1;
s2[i][j]=s2[i-1][j]+1;
}
if(a[i][j])
f[i][j]=min(f[i-1][j+1],min(s1[i][j+1],s2[i-1][j]))+1;
ans=max(ans,f[i][j]);
}
cout<<ans<<endl;
return 0;
}
贪婪的送礼者
解题思路: 用stl尝试一下此题
代码: 【借鉴】
#include<map>
#include<string>
#include<vector>
#include<iostream>
using namespace std;
int NP,money,num;
map<string,int> m;//存钱数
vector<string> id;//存人名
int main(){
cin>>NP;
string tmp;
for(int i=1;i<=NP;i++){
cin>>tmp;
id.push_back(tmp);//人名加进数组里(为了最后有序输出)
}
for(int i=1;i<=NP;i++){
cin>>tmp>>money>>num;//人 钱 送的人数
if(money==0||num==0)continue;//不送礼的直接跳
m[tmp]-=money;//送走了这么多钱
m[tmp]+=money%num;//多的还回来
for(int j=1;j<=num;j++){
cin>>tmp;
m[tmp]+=money/num;//得到钱数
}
}
for(vector<string>::iterator i=id.begin();i!=id.end();i++)
cout<<*i<<" "<<m[*i]<<endl;//遍历输出
return 0;
}
立体图
解题思路: 理解题意,想出思路比较重要,一、摆放顺序,二、坐标计算
代码: 【借鉴】
#include<stdio.h>
#include<iostream>
using namespace std;
const char Stick[6][8]=
{
"..+---+",
"./ /|",
"+---+ |",
"| | +",
"| |/.",
"+---+.."
};//单个方块
int a[55][55];
char Paint[550][550];//画布
inline void Draw(int x,int y)//涂鸦函数
{
int i,j;
for(i=0;i<6;i++)
for(j=0;j<7;j++)
if(Stick[6-i-1][j]!='.')
Paint[x-i][y+j]=Stick[6-i-1][j];//放置方块
}
int main()
{
int N,M,K(0),L,i,j,x,y;
scanf("%d%d",&N,&M);
L=4*M+2*N+1;//计算画布宽度
for(i=1;i<=N;i++)
for(j=1;j<=M;j++)
{
scanf("%d",&a[i][j]);
K=max(K,a[i][j]*3+2*(N-i+1)+1);//计算画布长度
}
for(i=1;i<=K;i++)
for(j=1;j<=L;j++)
Paint[i][j]='.';//画布初始化
for(i=1;i<=N;i++)
for(j=1;j<=M;j++)
{
x=K-2*(N-i);
y=2*(N-i)+4*(j-1)+1;//计算坐标
while(a[i][j]--)
{
Draw(x,y);//涂鸦
x-=3;//向上放
}
}
for(i=1;i<=K;i++)
{
for(j=1;j<=L;j++)
printf("%c",Paint[i][j]);
printf("\n");
}//打印画布
return 0;
}