USACO section 3.2 Magic Squares(STL+广搜)

36 篇文章 0 订阅
Magic Squares
IOI'96

Following the success of the magic cube, Mr. Rubik invented its planar version, called magic squares. This is a sheet composed of 8 equal-sized squares:

1234
8765

In this task we consider the version where each square has a different color. Colors are denoted by the first 8 positive integers. A sheet configuration is given by the sequence of colors obtained by reading the colors of the squares starting at the upper left corner and going in clockwise direction. For instance, the configuration of Figure 3 is given by the sequence (1,2,3,4,5,6,7,8). This configuration is the initial configuration.

Three basic transformations, identified by the letters `A', `B' and `C', can be applied to a sheet:

  • 'A': exchange the top and bottom row,
  • 'B': single right circular shifting of the rectangle,
  • 'C': single clockwise rotation of the middle four squares.

Below is a demonstration of applying the transformations to the initial squares given above:

A:
8765
1234
B:
4123
5876
C:
1724
8635

All possible configurations are available using the three basic transformations.

You are to write a program that computes a minimal sequence of basic transformations that transforms the initial configuration above to a specific target configuration.

PROGRAM NAME: msquare

INPUT FORMAT

A single line with eight space-separated integers (a permutation of (1..8)) that are the target configuration.

SAMPLE INPUT (file msquare.in)

2 6 8 4 5 7 3 1 

OUTPUT FORMAT

 

Line 1:A single integer that is the length of the shortest transformation sequence.
Line 2:The lexically earliest string of transformations expressed as a string of characters, 60 per line except possibly the last line.

SAMPLE OUTPUT (file msquare.out)

7
BCABCCB

思路:就是开个MAP判重,然后广搜到答案输出即可。不会超的。

失误点:弄不对是因为题目按要求的字母序最小的方法。所以按顺序比时只要长度短的更新,长度一样的不用更新。

 

代码:

/*
ID:nealgav1
LANG:C++
PROG:msquare
*/
#include<fstream>
#include<string>
#include<cstring>
#include<queue>
#include<map>
using namespace std;
ifstream cin("msquare.in");
ofstream cout("msquare.out");
const string mm="12345678";
map<string,string>mp;
string taget;
string STR;
///A,B,C三种操作
bool A(string a)
{ string z=a;
  string b(z.rbegin(),z.rend());
  a=b;
  STR=a;
  if(mp[a]!="")///如果原先无此量,返回true,入队列
  { if(mp[a].length()>mp[z].length()+1)///当长度比其小时更新,一样长不用更新
    {mp[a].clear();mp[a]=mp[z]+"A";return true;}
    else return true;
  }
  else if(mp[a]==mm)return true;
  else {mp[a]=mp[z]+"A";return false;}
}
bool B(string a)
{
  string z=a;
  string b;
  string s(z[3]+z.substr(0,3)+z.substr(5)+z[4]);
   a=s;
  STR=a;
  if(mp[a]!="")
  { if(mp[a].length()>mp[z].length()+1)
    {mp[a].clear();mp[a]=mp[z]+"B";return true;}
    else return true;
  }
  else if(mp[a]==mm)return true;
  else {mp[a]=mp[z]+"B";return false;}
}
bool C(string a)
{
   string z=a;
   string b;
   swap(a[1],a[2]);swap(a[1],a[5]);swap(a[1],a[6]);
   STR=a;
   if(mp[a]!="")
  { if(mp[a].length()>mp[z].length()+1)
    {mp[a].clear();mp[a]=mp[z]+"C";return true;}
    else return true;
  }
  else if(mp[a]==mm)return true;
  else {mp[a]=mp[z]+"C";return false;}
}
void bfs()
{
  string sss="12345678";
  queue<string>que;
  que.push("12345678");
  while(!que.empty())
  {
    sss=que.front();///遇到目标输出即可
    if(sss==taget)return;
    que.pop();
    if(!A(sss))que.push(STR);
    if(!B(sss))que.push(STR);
    if(!C(sss))que.push(STR);
  }
}
int main()
{
  string a;
  for(int i=0;i<8;i++)
  {cin>>a;taget+=a;}
  bfs();
  cout<<mp[taget].length()<<"\n";
  cout<<mp[taget]<<"\n";
  cin.close();
  cout.close();
}


 

 

 

 

USER: Neal Gavin Gavin [nealgav1]
TASK: msquare
LANG: C++

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.000 secs, 3408 KB]
   Test 2: TEST OK [0.000 secs, 3408 KB]
   Test 3: TEST OK [0.000 secs, 3408 KB]
   Test 4: TEST OK [0.000 secs, 3408 KB]
   Test 5: TEST OK [0.097 secs, 4464 KB]
   Test 6: TEST OK [0.205 secs, 5652 KB]
   Test 7: TEST OK [0.410 secs, 6972 KB]
   Test 8: TEST OK [0.616 secs, 7632 KB]

All tests OK.

YOUR PROGRAM ('msquare') WORKED FIRST TIME! That's fantastic -- and a rare thing. Please accept these special automated congratulations.

Here are the test data inputs:

------- test 1 ----
2 6 8 4 5 7 3 1
------- test 2 ----
1 2 3 4 5 6 7 8
------- test 3 ----
6 7 4 1 8 5 2 3
------- test 4 ----
5 1 2 4 3 7 8 6
------- test 5 ----
6 1 5 4 3 2 7 8
------- test 6 ----
4 1 2 3 5 8 7 6
------- test 7 ----
3 4 2 1 5 6 7 8
------- test 8 ----
4 3 1 2 5 6 7 8
Keep up the good work!

 

Magic Squares
Hal Burch

This is a shortest path problem, where the nodes of the graph are board arrangements, and edges are transformations. There are 8! = 40,320 possible board arrangements, so the problem can be solved using breadth-first search (since all edges are of unit length.

Number the boards in increasing order lexicographically, so that indexing is simpler.

In order to simplify the calculations, walk the path backward (start at the ending arrangement given, find the minimum path to the initial configuration following reverse transformations). Then, walk backwards in the resulting tree to determine the path.

#include <stdio.h>
#include <assert.h>

/* the distance from the initial configuration (+1) */
/* dist == 0 => no know path */
int dist[40320];

/* calculate the index of a board */
int encode(int *board)
 {
  static int mult[8] = 
    {1, 8, 8*7, 8*7*6, 8*7*6*5,
     8*7*6*5*4, 8*7*6*5*4*3, 8*7*6*5*4*3*2};
  
  /* used to calculate the position of a number within the
     remaining ones */
  int look[8] = {0, 1, 2, 3, 4, 5, 6, 7};
  int rlook[8] = {0, 1, 2, 3, 4, 5, 6, 7};
  /* rlook[look[p]] = p and look[rlook[p]] = p */

  int lv, rv;
  int t;

  rv = 0;
  for (lv = 0; lv < 8; lv++)
   {
    t = look[board[lv]]; /* the rank of the board position */
    assert(t < 8-lv); /* sanity check */
    rv += t * mult[lv]; 

    assert(look[rlook[7-lv]] == 7-lv); /* sanity check */

    /* delete t */
    look[rlook[7-lv]] = t;
    rlook[t] = rlook[7-lv];
   }
  return rv;
 }

/* the set of transformations, in order */
static int tforms[3][8] = { {8, 7, 6, 5, 4, 3, 2, 1},
     {4, 1, 2, 3, 6, 7, 8, 5}, {1, 7, 2, 4, 5, 3, 6, 8} };

void do_trans(int *inboard, int *outboard, int t)
 { /* calculate the board (into outboard) that results from doing
      the t'th transformation to inboard */
  int lv;
  int *tform = tforms[t];

  assert(t >= 0 && t < 3);

  for (lv = 0; lv < 8; lv++)
    outboard[lv] = inboard[tform[lv]-1];
 }

void do_rtrans(int *inboard, int *outboard, int t)
 { /* calculate the board (into outboard) that which would result
      in inboard if the t'th transformation was applied to it */
  int lv;
  int *tform = tforms[t];

  assert(t >= 0 && t < 3);

  for (lv = 0; lv < 8; lv++)
    outboard[tform[lv]-1] = inboard[lv];
 }

/* queue for breadth-first search */
int queue[40325][8];
int qhead, qtail;

/* calculate the distance from each board to the ending board */
void do_dist(int *board)
 {
  int lv;
  int t1;
  int d, t;

  qhead = 0;
  qtail = 1;

  /* the ending board is 0 steps away from itself */
  for (lv = 0; lv < 8; lv++) queue[0][lv] = board[lv];
  dist[encode(queue[0])] = 1; /* 0 steps (+ 1 offset for dist array) */

  while (qhead < qtail)
   {
    t1 = encode(queue[qhead]);
    d = dist[t1];

    /* for each transformation */
    for (lv = 0; lv < 3; lv++)
     {
      /* apply the reverse transformation */
      do_rtrans(queue[qhead], queue[qtail], lv);

      t = encode(queue[qtail]);
      if (dist[t] == 0) 
       { /* found a new board position!  add it to queue */
        qtail++;
        dist[t] = d+1;
       }
     }

    qhead++;
   }
 }

/* find the path from the initial configuration to the ending board */
void walk(FILE *fout)
 {
  int newboard[8];
  int cboard[8];
  int lv, lv2;
  int t, d;

  for (lv = 0; lv < 8; lv++) cboard[lv] = lv;
  d = dist[encode(cboard)];
  /* start at the ending board */
  while (d > 1)
   {
    for (lv = 0; lv < 3; lv++)
     {
      do_trans(cboard, newboard, lv);
      t = encode(newboard);
      if (dist[t] == d-1) /* we found the previous board! */
       {
        /* output transformatino */
        fprintf (fout, "%c", lv+'A');

	/* find the rest of the path */
        for (lv2 = 0; lv2 < 8; lv2++) cboard[lv2] = newboard[lv2];
	break;
       }
     }
    assert(lv < 3);
    d--;
   }
  fprintf (fout, "\n");
 }

int main(int argc, char **argv)
 {
  FILE *fout, *fin;
  int board[8];
  int lv;

  if ((fin = fopen("msquare.in", "r")) == NULL)
   {
    perror ("fopen fin");
    exit(1);
   }
  if ((fout = fopen("msquare.out", "w")) == NULL)
   {
    perror ("fopen fout");
    exit(1);
   }

  for (lv = 0; lv < 8; lv++) 
   {
    fscanf (fin, "%d", &board[lv]);
    board[lv]--; /* use 0-based instead of 1-based */
   }

  /* calculate the distance from each board to the ending board */
  do_dist(board);

  for (lv = 0; lv < 8; lv++) board[lv] = lv;

  /* output the distance from and the path from the initial configuration */
  fprintf (fout, "%d\n", dist[encode(board)]-1);
  walk(fout);

  return 0;
 }

 

 

 

Thanks for your submission!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是P4087 [USACO17DEC]Milk Measurement的c++代码: ```c++ #include<bits/stdc++.h> using namespace std; int n,d,i,x,minn=1e9,maxn=-1e9,sum=7;//注意sum要初始化为7,因为一开始有三个人挤奶! map<int,int> mp; struct node{ int day,milk,id;//day表示某一天,milk表示这一天的产奶量,id表示这头牛的编号 }a[100010]; bool cmp(node x,node y){ return x.day<y.day; } int main(){ scanf("%d%d",&n,&d); for(i=1;i<=n;i++){ scanf("%d%d%d",&a[i].day,&a[i].id,&a[i].milk); minn=min(minn,a[i].id);//记录最小的牛的编号 maxn=max(maxn,a[i].id);//记录最大的牛的编号 } sort(a+1,a+n+1,cmp);//排序 for(i=1;i<=n;i++){ int p=a[i].id; mp[p]+=a[i].milk;//记录每头牛产奶总量 if(mp[p]-a[i].milk>=mp[minn]&&mp[p]>=mp[minn]){//如果这头牛的产奶总量减去这一天的产奶量后等于最小产奶量且这头牛的产奶总量大于等于最小产奶量 sum--; } if(mp[p]>=mp[maxn]&&mp[p]-a[i].milk<mp[maxn]){//如果这头牛的产奶总量大于等于最大产奶量且这头牛的产奶总量减去这一天的产奶量小于最大产奶量 sum++; } if(mp[p]-a[i].milk<mp[maxn]&&mp[p]>=mp[maxn]){//如果这头牛的产奶总量减去这一天的产奶量小于最大产奶量且这头牛的产奶总量大于等于最大产奶量 if(mp[maxn]-mp[p]+a[i].milk>0)sum++; } mp[p]-=a[i].milk;//减去这一天的产奶量 if(i==n||a[i].day!=a[i+1].day){//如果到了新的一天或者到了最后一天 if(mp[maxn]!=mp[a[i].id]&&mp[a[i].id]>=mp[maxn])sum++;//如果这头牛的产奶总量不等于最大产奶量且这头牛的产奶总量大于等于最大产奶量 if(mp[maxn]==mp[a[i].id]){//如果这头牛的产奶总量等于最大产奶量 if(a[i].id==maxn)sum+=0;//如果这头牛就是最大产奶量的牛,那么不需要增加计数器 else sum++;//否则需要增加计数器 } if(mp[minn]!=mp[a[i].id]&&mp[a[i].id]>=mp[minn])sum++;//如果这头牛的产奶总量不等于最小产奶量且这头牛的产奶总量大于等于最小产奶量 if(mp[minn]==mp[a[i].id]){ if(a[i].id==minn)sum+=0;//如果这头牛就是最小产奶量的牛,那么不需要增加计数器 else sum++;//否则需要增加计数器 } } } printf("%d\n",sum); return 0; } ``` 该题的解题思路是模拟,需要注意细节问题。我们可以首先将输入的数据按天数排序,然后模拟每一天挤奶的情况,并根据题目要求进行计数即可。具体细节请见代码注释。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值