【noip停课集训,10.12】【#2training】
来源:互联网 发布:手机健康体检软件 编辑:程序博客网 时间:2024/05/16 12:50
Description
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 x
where the only legal operation is to exchange 'x' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle:
1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8 9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12 13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x r-> d-> r->
The letters in the previous row indicate which neighbor of the 'x' tile is swapped with the 'x' tile at each step; legal values are 'r','l','u' and 'd', for right, left, up, and down, respectively.
Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and
frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course).
In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three
arrangement.
Input
1 2 3 x 4 6 7 5 8
is described by this list:
1 2 3 x 4 6 7 5 8
Output
Sample Input
2 3 4 1 5 x 7 6 8
Sample Output
ullddrurdllurdruldr
第一题典型八数码,然而由于开始写的string+map,超时n次,然后后来手动hash,又因为各种脑抽调试了n久,并且后来才发现是求路径而不是最小次数,但经过各种努力终于还是AC了QAQ,
思路倒是挺简单的,直接BFS,hash方式一般都用的康托展开,阶乘预处理下就好了,然后就是hash时把二维转成一维,扩展时把一维转成二维,这个也比较简单。。至于其他的就是一般的BFS过程了。。输出路径我是直接从终点往起点搜,这样就记录前驱直接输出,不用在递归或是重新记录。。
#include<cstdio>#include<iostream>#include<string>#include<algorithm>#include<queue>#include<cstring>using namespace std;const int MAX=1000000;int sr[9],po;int fan[9]={1,1,2,6,24,120,720,5040,40320};bool visit[MAX];char path[MAX];int pre[MAX];struct lmx{ int a[9]; int pos;};lmx s,t,h;int temp = 0;int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};char st[5]="durl";int str;int kgto(int *m,int n){ int i,j,num,s=0; for(i=0;i<n-1;i++) { num=0; for(j=i+1;j<n;j++) { if(m[j]<m[i]) num++; } s+=num*fan[8-i]; } return s;}int bfs(){ memset(visit,false,sizeof(visit)); int i,val,x,y,xx,yy; queue<lmx>q; for(i=0;i<8;i++)//倒着搜方便输出 { s.a[i]=i+1; } s.a[8]=0; s.pos=8; q.push(s); val=kgto(s.a,9); str = val; visit[val]=true; while(!q.empty()) { h=q.front(); q.pop(); x=h.pos/3; y=h.pos%3; int id = kgto(h.a,9); for(i=0;i<4;i++) { xx=x+dir[i][0]; yy=y+dir[i][1]; if(xx>=0&&xx<3&&yy>=0&&yy<3) { t=h; swap(t.a[h.pos],t.a[xx*3+yy]); t.pos=3*xx+yy; val=kgto(t.a,9); if(visit[val]==false) { visit[val]=true; pre[val] = id; path[val] = st[i]; q.push(t); if(val == temp)return 1; } } } }}int main(){ char ch[105]; int i; while(gets(ch)) { int count = 0; for(int i = 0; i < strlen(ch); ++i){ if(ch[i] >= '0' && ch[i] <= '9')sr[count] = ch[i] - '0',po = count++; else if(ch[i] == 'x')sr[count] = 0,po = count++; } temp=kgto(sr,9); bfs(); if(visit[temp]==false) puts("unsolvable"); else{ int id = temp; while(id != str){ printf("%c",path[id]); id = pre[id]; } } } return 0;}这是我写的
以下是另一种
#include <cstdio>#include <cstring>#include <queue>#include <algorithm>using std::queue;const int dx[] = {0, 0, 1, -1};const int dy[] = {1, -1, 0, 0};const char dir[] = {'r', 'l', 'd', 'u'};const int fac[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800};int n = 9;struct Node{int a[10], status, pos;int step, now;void Get(){status = 0;for(int i = 0; i < n; i++){int t = 0;for(int j = i + 1; j < n; j++)if(a[j] < a[i]) t++;status += t * fac[n-i-1];}}}S, T;bool hash[3628800+100];queue<Node> Q;int path[3628800+100], CNT = 0;int pre[3628800+100];bool expand(Node &nd, Node tmp, int k){nd = tmp;path[++CNT] = k; nd.now = CNT; pre[CNT] = tmp.now;int x = tmp.pos / 3;int y = tmp.pos % 3;int nx = x + dx[k];int ny = y + dy[k];if(nx < 0 || nx > 2) return 0;if(ny < 0 || ny > 2) return 0;int npos = nx * 3 + ny;std::swap(nd.a[nd.pos], nd.a[npos]);nd.pos = npos; nd.Get();return 1;}void PRINT(Node now){for(int i = 0; i < 9; i++){printf("%d ", now.a[i]);if((i+1) % 3 == 0) puts("");}printf("%d\n\n", now.status);}void writeans(int now){if(pre[now] == -1) return;writeans(pre[now]);puts("");putchar(dir[path[now]]);}void BFS(){memset(pre, -1, sizeof(pre));Q.push(S); hash[S.status] = 1; S.now = -1;while(!Q.empty()){Node now = Q.front(); Q.pop();if(now.step > 100) break;if(now.status == T.status){//PRINT(now);writeans(now.now);return;}//PRINT(now);Node nd;for(int k = 0; k < 4; k++){if(!expand(nd, now, k)) continue;if(!hash[nd.status]){hash[nd.status] = 1;Q.push(nd);}}}puts("unsolvable");}int main(){//freopen("A.out", "w", stdout);for(int i = 0; i < n; i++){char ch; scanf(" %c", &ch);if(ch == 'x'){S.a[i] = 0;S.pos = i;}else S.a[i] = ch - '0';}S.Get(); S.step = 0;for(int i = 0; i < n-1; i++) T.a[i] = i+1;T.a[n-1] = 0; T.Get();BFS();return 0;}
Description
At the beginning, the two dices may face different(which means there exist some i, a i ≠ b i). Ddy wants to make the two dices look the same from all directions(which means for all i, a i = b i) only by the following four rotation operations.(Please read the picture for more information)
Now Ddy wants to calculate the minimal steps that he has to take to achieve his goal.
Input
For each case, the first line consists of six integers a 1,a 2,a 3,a 4,a 5,a 6, representing the numbers on dice A.
The second line consists of six integers b 1,b 2,b 3,b 4,b 5,b 6, representing the numbers on dice B.
Output
Sample Input
1 2 3 4 5 61 2 3 4 5 61 2 3 4 5 61 2 5 6 4 31 2 3 4 5 61 4 2 5 3 6
Sample Output
03-1
这个是WA
#include<cstdio>#include<iostream>#include<queue>#include<cstring>using namespace std;struct node{int s[6];int cnt;}st,ed;char s[20];bool flag = false;int ans = -1;int edHash = 0;bool Hash[850000];int getHash(int *a){int t = 1;for(int i = 0; i < 6; ++i)t = t * 7 + a[i];return t;}bool check(node n){int id = getHash(n.s);if(Hash[id])return false;Hash[id] = 1;if(edHash == id)flag = true;return true;}node expand(node n,int i){switch(i){case 0 :{swap(n.s[0],n.s[2]);swap(n.s[1],n.s[3]);swap(n.s[0],n.s[1]);break;}case 1 :{swap(n.s[0],n.s[2]);swap(n.s[1],n.s[3]);swap(n.s[2],n.s[3]);break;}case 2 :{swap(n.s[0],n.s[4]);swap(n.s[1],n.s[5]);swap(n.s[0],n.s[1]);break;}case 3 :{swap(n.s[0],n.s[4]);swap(n.s[1],n.s[5]);swap(n.s[4],n.s[5]);break;}}n.cnt++;return n;}bool bfs(){queue<node>q;q.push(st);node nd,xd;int stHash = getHash(st.s);if(stHash == edHash)return 1;while(q.size()){nd = q.front();q.pop();for(int i = 0; i < 4; ++i){xd = expand(nd,i);if(check(xd)){q.push(xd);if(flag){ans = xd.cnt;return 1;}}}}return 0;}int main(){while(gets(s)){flag = false;ans = -1;memset(Hash,0,sizeof(Hash));int count = 0;for(int i = 0; i < strlen(s); ++i){if(s[i] >= '0' && s[i] <= '9')st.s[count++] = s[i] - '0';}gets(s);count = 0;for(int i = 0; i < strlen(s); ++i){if(s[i] >= '0' && s[i] <= '9')ed.s[count++] = s[i] - '0';}Hash[getHash(st.s)] = 1;st.cnt = 0;edHash = getHash(ed.s);if(bfs())printf("%d\n",ans == -1 ? 0 : ans);else printf("%d\n",-1);}return 0;}
#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>using namespace std;struct node{ int s1,s2,s3,s4,s5,s6; int sum;} q[800000];int a[7],b[7];int c[7][7][7][7][7][7];void bfs(){ memset(c,0,sizeof(c)); struct node t,r; t.s1=b[1]; t.s2=b[2]; t.s3=b[3]; t.s4=b[4]; t.s5=b[5]; t.s6=b[6]; t.sum=0; int k=0,l=0; q[l++]=t; while(k<l) { t=q[k++]; if(t.s1==a[1] && t.s2==a[2] && t.s3==a[3] && t.s4==a[4] && t.s5==a[5] && t.s6==a[6]) { printf("%d\n",t.sum); return ; } for(int i=0; i<4; i++) { if(i==0) { r.s1=t.s4; r.s2=t.s3; r.s3=t.s1; r.s4=t.s2; r.s5=t.s5; r.s6=t.s6; } else if(i==1) { r.s1=t.s3; r.s2=t.s4; r.s3=t.s2; r.s4=t.s1; r.s5=t.s5; r.s6=t.s6; } else if(i==2) { r.s1=t.s5; r.s2=t.s6; r.s3=t.s3; r.s4=t.s4; r.s5=t.s2; r.s6=t.s1; } else { r.s1=t.s6; r.s2=t.s5; r.s3=t.s3; r.s4=t.s4; r.s5=t.s1; r.s6=t.s2; } if(!c[r.s1][r.s2][r.s3][r.s4][r.s5][r.s6]) { c[r.s1][r.s2][r.s3][r.s4][r.s5][r.s6]=1; r.sum=t.sum+1; q[l++]=r; } } } printf("-1\n");}int main(){ while(~scanf("%d",&a[1])) { for(int i=2; i<=6; i++) scanf("%d",&a[i]); for(int i=1; i<=6; i++) scanf("%d",&b[i]); bfs(); } return 0;}这个AC
第三题:UVAlive 6470:
此题很明显是个博弈,所以两人都很聪明
我们可以用记忆化搜索,设f[x][y][z]是到x,y,z这个状态的时候会输还是会赢,有我们等会的思路,可知无论是什么样的巧克力,到这步状态的x,y,z输赢不会变;
我们就枚举吃哪块巧克力,注意用到一个博弈的思想:当前扩展出的所有下一状态必输,那么当前才必赢。这个很重要
#include<cstdio>#include<iostream>#include<cstring>using namespace std;int f[105][105][105];int T;bool is_win(int x,int y,int z){if(x == 1 && y == 0 && z == 0)return 1;if(f[x][y][z] != -1)return f[x][y][z];bool flag = 1;for(int i = 2; i <= x; ++i){int xx = i - 1, yy = y, zz = z;yy = min(xx,yy);zz = min(zz,xx);//吃掉巧克力的状态,下同if(is_win(xx,yy,zz))flag = 0;//如果下一次赢了,那此次必输,下同}for(int i = 1; i <= y; ++i){int xx = x, yy = i - 1, zz = z;zz = min(zz,yy);if(is_win(xx,yy,zz))flag = 0;}for(int i = 1; i <= z; ++i){int xx = x, yy = y, zz = i - 1;if(is_win(xx,yy,zz))flag = 0;}return f[x][y][z] = flag;}void sovle(){int p,q,r;scanf("%d%d%d",&p,&q,&r);for(int i = 2; i <= p; ++i){int xx = i - 1, yy = q, zz = r;yy = min(xx,yy);zz = min(zz,xx);//吃掉巧克力后的状态,下同if(is_win(xx,yy,zz)){printf("W %d 1\n",i);return ;}}for(int i = 1; i <= q; ++i){int xx = p, yy = i - 1, zz = r;zz = min(zz,yy);if(is_win(xx,yy,zz)){printf("W %d 2\n",i);return ;}}for(int i = 1; i <= r; ++i){int xx = p,yy = q, zz = i - 1;if(is_win(xx,yy,zz)){printf("W %d 3\n",i);return ;}}printf("L\n");}int main(){scanf("%d",&T);memset(f,-1,sizeof(f));while(T--){int k;scanf("%d",&k);printf("%d ",k);sovle();}return 0;}
Description
Thanks a lot for helping Harry Potter in finding the Sorcerer's Stone of Immortality in October. Did we not tell you that it was just an online game ? uhhh! now here is the real onsite task for Harry. You are given a magrid S ( a magic grid ) having R rows and C columns. Each cell in this magrid has either a Hungarian horntail dragon that our intrepid hero has to defeat, or a flask of magic potion that his teacher Snape has left for him. A dragon at a cell (i,j) takes away |S[i][j]| strength points from him, and a potion at a cell (i,j) increases Harry's strength by S[i][j]. If his strength drops to 0 or less at any point during his journey, Harry dies, and no magical stone can revive him.
Harry starts from the top-left corner cell (1,1) and the Sorcerer's Stone is in the bottom-right corner cell (R,C). From a cell (i,j), Harry can only move either one cell down or right i.e., to cell (i+1,j) or cell (i,j+1) and he can not move outside the magrid. Harry has used magic before starting his journey to determine which cell contains what, but lacks the basic simple mathematical skill to determine what minimum strength he needs to start with to collect the Sorcerer's Stone. Please help him once again.
Input (STDIN):
The first line contains the number of test cases T. T cases follow. Each test case consists of R C in the first line followed by the description of the grid in R lines, each containing C integers. Rows are numbered 1 to R from top to bottom and columns are numbered 1 to C from left to right. Cells with S[i][j] < 0 contain dragons, others contain magic potions.
Output (STDOUT):
Output T lines, one for each case containing the minimum strength Harry should start with from the cell (1,1) to have a positive strength through out his journey to the cell (R,C).
Constraints:
1 ≤ T ≤ 5
2 ≤ R, C ≤ 500
-10^3 ≤ S[i][j] ≤ 10^3
S[1][1] = S[R][C] = 0
Sample Input:
3
2 3
0 1 -3
1 -2 0
2 2
0 1
2 0
3 4
0 -2 -3 1
-1 4 0 -2
1 -2 -3 0
Sample Output:
2
1
2
Explanation:
Case 1 : If Harry starts with strength = 1 at cell (1,1), he cannot maintain a positive strength in any possible path. He needs at least strength = 2 initially.
Case 2 : Note that to start from (1,1) he needs at least strength = 1.
Hint
#include<cstdio>#include<iostream>#include<cstring>using namespace std;int T;int map[500 + 5][500 + 5];int R,C;int f[500 + 5][500 + 5];bool check(int st){memset(f,0,sizeof(f));f[1][1] = st;for(int i = 1; i <= R; ++i){for(int j = 1; j <= C; ++j){if(f[i][j])continue;if(f[i - 1][j] > 0 && f[i][j - 1] > 0)f[i][j] = max(f[i - 1][j], f[i][j - 1]) + map[i][j];else if(f[i - 1][j] > 0)f[i][j] = f[i - 1][j] + map[i][j];else if(f[i][j - 1] > 0)f[i][j] = f[i][j - 1] + map[i][j];else f[i][j] = -0x3f3f3f3f;}}if(f[R][C] > 0)return 1;else return 0;}int main(){scanf("%d",&T);while(T--){scanf("%d%d",&R, &C);int l = 0,r = 250000000;for(int i = 1; i <= R; ++i){for(int j = 1; j <= C; ++j){scanf("%d",&map[i][j]);}}while(l < r){int m = (l + r) >> 1;if(check(m))r = m;else l = m + 1;}printf("%d\n",l);}return 0;}总之,这几道题思路还是比较简单,但是写的时候调试了好久,代码水平有待提高,加油!!
- 【noip停课集训,10.12】【#2training】
- 【停课集训10.13】【#3 training】
- 【停课集训 10.14】【#4 training】
- 致NOIP前 停课记录~~
- NOIP停课以来比赛总结
- 10月停课集训第二周总结
- 【NOIP】10.27集训总结
- 【NOIP】10.28集训总结
- 【NOIP】10.29集训总结
- NOIP集训总结
- noip济南集训-10.1上午
- NOIP集训Week 1总结
- NOIP集训Week 3总结
- NOIP集训Week 5总结
- NOIP集训Week 6总结
- NOIP集训Week 7总结
- [Dairy 2:2015.6.18] 停课之前
- 【复习+整理】【题解】noip集训考试1
- 利用模拟退火算法求解TSP问题(C++实现)
- samba config
- 软件测试人员与QA的区别
- 哈夫曼树——C++实现
- 内存调优
- 【noip停课集训,10.12】【#2training】
- 八皇后问题(Python实现)
- Mongodb总结2-Java版本的HelloWorld-CRUD例子
- HDR技术
- 前端基础学习总结151012
- Fragment
- HM各个类中保存的数据类型以及之间的联系
- C#服务器客户端通信简单实现
- Linux进程间通信——使用共享内存