上周周赛题目,网上都能直接找到
其实还是很水的,只要搜索学的还行的几乎都能AK
Problem A HDU 1036 Average is not Fast Enough!
Problem B CodeForces 652B z-sort
Problem C HDU 1312 Red and Black
Problem D HDU 1429 胜利大逃亡(续)
Problem E HDU 1026 Ignatius and the Princess I
首先是A题,题意表示一下看不懂,但是ACM这类英文题一般都先看样例会更快的理解题意。
A - Average is not Fast Enough!
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int main()
{
int n;
double d;
int a;
scanf("%d%lf",&n,&d);
while(~scanf("%d",&a)){
int h,m,s;
int sum = 0;
char ss[20]; //因为如果是--:--:--的话,就不能直接用%d读
bool flag = true; // 用来标记记录里是否有--:--:--
getchar();
for(int i=0;i<n;i++){
scanf("%s",ss);
if(ss[0]=='-') flag = false;
sscanf(ss,"%d:%d:%d",&h,&m,&s);
sum += h*3600 + m*60 + s;
}
if(flag){
sum = int(sum/d + 0.5); // 整除的处理
printf("%3d: %d:%2.2d min/km\n",a,sum/60,sum%60);
}else {
printf("%3d: -\n",a);
}
}
return 0;
}
代码写的不好请不要见怪
然后是B题,B题如果数据小可以暴力搜索,但显然一般先想想有没有更好的方法再去写会更好一点。然后数据貌似很水,被我水过了。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
int a[1010];
int ans[1010];
int main()
{
int n;
while(~scanf("%d",&n)){
for(int i=0;i<n;i++) scanf("%d",&a[i]);
sort(a,a+n);//直接排序,前一半肯定都比后一半小,所以把后一半都放偶数位,前一半都放奇数位
int i=0,j=0,tot=0;
j = (n-1)/2 + 1;
for(;tot<n;tot++){
if((tot+1)&1){
ans[tot] = a[i++];
}else {
ans[tot] = a[j++];
}
}
for(int i=0;i<n;i++) {printf("%d",ans[i]);if(i<n-1) printf(" ");}
printf("\n");
}
return 0;
}
水过了B题,然后发现C题更水,就我都能一遍敲出来······
C - Red and Black
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int wayx[] = {1,-1,0,0};
const int wayy[] = {0,0,1,-1};
int mp[30][30];
int uesd[30][30];
int w,h;
int ans;
void dfs(int x,int y)
{
if(x<=0||x>h||y<=0||y>w||uesd[x][y]==1||mp[x][y]==0) return; //检查边界以及走没走过
else {
ans++;
uesd[x][y]=1;
}
for(int i=0;i<4;i++){ //四个方向
int r,c;
r = x + wayx[i];
c = y + wayy[i];
dfs(r,c);
}
return ;
}
int main()
{
while(scanf("%d%d",&w,&h),w||h){
memset(uesd,0,sizeof(uesd));
memset(mp,0,sizeof(mp));
ans = 0;
getchar();
int x,y;
for(int i=1;i<=h;i++){
for(int j=1;j<=w;j++){
char c;
scanf("%c",&c);
mp[i][j] = (c=='.'||c=='@') ? 1 : 0;
if(c=='@'){x = i,y = j;}
}
getchar();//读的时候要小心这些细节
}
dfs(x,y);
printf("%d\n",ans);
}
return 0;
}
然后D题开始不水了,这题要一点技巧。
D - 胜利大逃亡(续)
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <queue>
#include <iostream>
using namespace std;
const int dir[4][2] = {1,0,-1,0,0,1,0,-1};
int n,m,t;
int sx,sy,ex,ey;
char mp[21][21];
int mark[21][21][1024];//用二进制思想:通过拥有钥匙数来控制不走回路
struct node
{
int x,y;
int key;
int flag[10]; // 表示拥有的钥匙
int step;
};
int a[11]={1,2,4,8,16,32,64,128,256,512}; //二进制打表
bool check(int x,int y,int z,int step) //检查
{
if(x>=0&&x<n&&y>=0&&y<m){
if(mp[x][y]!='*'&&mark[x][y][z]==0&&step<t){
return true;
}
}
return false;
}
void bfs()
{
node v,p;
queue<node> q;
memset(mark,0,sizeof(mark));
p.x = sx , p.y = sy;
p.step = 0;
p.key = 0;
for(int i=0;i<10;i++) p.flag[i] = 0;
q.push(p);
mark[sx][sy][0] = 1;
while(!q.empty()){
p = q.front();
q.pop();
for(int i=0;i<4;i++){
v = p;
v.x = p.x + dir[i][0];
v.y = p.y + dir[i][1];
v.step = p.step + 1;
if(check(v.x,v.y,v.key,v.step)){
if(v.x==ex&&v.y==ey){
printf("%d\n",v.step);
return ;
}
else if(mp[v.x][v.y]>='a'&&mp[v.x][v.y]<='j'){
if(v.flag[mp[v.x][v.y]-'a']==0){ //注意这里如果有这把钥匙,就不要更改钥匙状态
v.flag[mp[v.x][v.y]-'a'] = 1;
v.key += a[mp[v.x][v.y]-'a'];
}
mark[v.x][v.y][v.key] = 1;
q.push(v);
}
else if(mp[v.x][v.y]>='A'&&mp[v.x][v.y]<='J'){
if(v.flag[mp[v.x][v.y]-'A']==1){
mark[v.x][v.y][v.key] = 1;
q.push(v);
}
}else {
mark[v.x][v.y][v.key] = 1;
q.push(v);
}
}
}
}
printf("-1\n");
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&t)){
getchar();
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
scanf("%c",&mp[i][j]);
if(mp[i][j]=='@'){
sx = i;
sy = j;
}
if(mp[i][j]=='^'){
ex = i;
ey = j;
}
}
getchar();
}
mp[sx][sy] = '.';
bfs();
}
return 0;
}
对于D题,我只能表示我码力不够,T-T,敲了半天
最后E题,额,其实比D题稍微水点,不过貌似要注意以一下内存问题
同时那个输出问题也要注意一下,不然这种搜索题目一旦出错,找错会很难,别问我怎么知道T-T
E - Ignatius and the Princess I
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <queue>
#include <iostream>
using namespace std;
struct node
{
int x,y;
int step;
friend bool operator < (node n1,node n2)
{
return n2.step<n1.step;
}
};
int mp[105][105];
int flag[105][105];
int cnt[105][105]; // 记录要打的怪的HP
int ways[4][2] = {1,0,-1,0,0,1,0,-1};
int n,m,tim;
int check(int x,int y)
{
if(x<0||y>=m||y<0||x>=n){
return 1;
}
if(mp[x][y]==-1){
return 1;
}
return 0;
}
int bfs()
{
priority_queue<node> q;
node a,next;
a.x = 0;
a.y = 0;
a.step = 0;
mp[0][0] = -1;
q.push(a);
while(!q.empty()){
a = q.top();
q.pop();
if(a.x==n-1&&a.y==m-1){
return a.step;
}
for(int i=0;i<4;i++){
next = a;
next.x += ways[i][0];
next.y += ways[i][1];
if(check(next.x,next.y)){
continue;
}
next.step = a.step + mp[next.x][next.y] + 1; // 记录时间
mp[next.x][next.y] = -1; // 标记为走过
flag[next.x][next.y] = i+1; //记录朝向
q.push(next);
}
}
return 0;
}
void print(int x,int y)
{
int n_x,n_y;
if(!flag[x][y])
return;
n_x = x - ways[flag[x][y]-1][0];
n_y = y - ways[flag[x][y]-1][1];
print(n_x,n_y);
printf("%ds:(%d,%d)->(%d,%d)\n",tim++,n_x,n_y,x,y);
while(cnt[x][y]--)
{
printf("%ds:FIGHT AT (%d,%d)\n",tim++,x,y);
}
}
int main()
{
while(~scanf("%d%d",&n,&m)){
memset(mp,0,sizeof(mp));
memset(flag,0,sizeof(flag));
memset(cnt,0,sizeof(cnt));
char s[105];
for(int i=0;i<n;i++){
scanf("%s",s);
for(int j=0;s[j];j++){ //对元素进行处理,方便后面处理
if(s[j]=='.'){
mp[i][j] = 0;
}else if(s[j]=='X'){
mp[i][j] = -1;
}else {
mp[i][j] = cnt[i][j] = s[j] - '0'; // 是怪
}
}
}
int ans=0;
ans = bfs();
if(ans){
printf("It takes %d seconds to reach the target position, let me show you the way.\n",ans);
tim = 1;
print(n-1,m-1);
}else {
printf("God please help our poor hero.\n");
}
printf("FINISH\n");
}
return 0;
}
敲完解题,仔细回味发现这种dfs和bfs一定要细心,不然找bug会让非常难找,另外是逻辑的重要性,以及对题目各种元素属性,要求的理解,估算空间,估算时间。
特别是做题的时候,一定要分清是用bfs还是dfs
每一题都应该有那么一个比较清晰的思路,思路不清晰就想清楚再敲,不然很碍事。
最后最重要的,这种题目还是自己码力不足,还得继续努力。
以上内容有一定是自己看过别人的才写出来的,如果有冒犯,请原谅
如果有错误请给予更正,谢谢