上週周賽題目,網上都能直接找到
其實還是很水的,只要搜索學的還行的幾乎都能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
每一題都應該有那麼一個比較清晰的思路,思路不清晰就想清楚再敲,不然很礙事。
最後最重要的,這種題目還是自己碼力不足,還得繼續努力。
以上內容有一定是自己看過別人的才寫出來的,如果有冒犯,請原諒
如果有錯誤請給予更正,謝謝