文章目录
- POJ1753 Flip Game 搜索+位运算
- POJ2965 The Pilots Brothers' refrigerator 搜索 +位运算
- POJ1328 Radar Installation 思维+贪心
- POJ2109 Power of Cryptography 库函数
- POJ2586 Y2K Accounting Bug
- POJ3295 Tautology 思维+计算模拟
- POJ1068 Parencodings 模拟+思维
- POJ2632 Crashing Robots 模拟+思维
- POJ1573 Robot Motion 模拟+思维
- POJ2996 Help Me with the Game 模拟+坐标变换
- POJ2993 Emag eht htiw Em Pleh 模拟+坐标变换
POJ1753 Flip Game 搜索+位运算
题目地址POJ1753 Flip Game
题目大意:一个4*4的棋盘放有黑色和白色两种棋子,有如下操作,每翻转一个棋子,将其上下左右和其本身的颜色翻转,问最少多少次翻转能使整个棋盘的棋子全为黑色或者全为白色。
思路:由于这个棋盘的规模比较小,所以我们可以遍历搜索,每个棋子都是只有两种情况,要么白色要么黑色,直接深搜遍历所有情况,取最小值即可。对于翻转操作,其实用位运算更方便一些。
AC代码:
/*
**http://poj.org/problem?id=1753
*/
#include <cstdlib>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int str[5][5];
int ans = INF;
int cnt;
void turn(int x, int y)
{
str[x][y]^=1;
if(x-1>=1) str[x-1][y]^=1;
if(x+1<=4) str[x+1][y]^=1;
if(y+1<=4) str[x][y+1]^=1;
if(y-1>=1) str[x][y-1]^=1;
}
bool check()
{
int t = str[1][1];
for(int i = 1;i <= 4;i ++)
for(int j = 1;j <= 4;j++)
if(t!=str[i][j])
return false;
return true;
}
void dfs(int x, int y,int cnt)
{
if(check()){ // check
if(cnt < ans) ans = cnt;
return ;
}
if(x == 5) return ;
// 翻它
turn(x, y); // change
if(y == 4) dfs(x + 1, 1, cnt + 1); // 换行
else dfs(x, y + 1, cnt + 1);
turn(x, y); // back 翻回来
// 不翻不翻
if(y == 4) dfs(x + 1, 1, cnt);
else dfs(x, y + 1, cnt);
}
void solve()
{
for(int i = 1;i <= 4;i ++)
{
for(int j = 1;j <=4;j++)
{
char ch;
ch = getchar();
while(ch=='\n')ch=getchar();
if(ch=='b')
{
str[i][j]=1;
}
else
{
str[i][j]=0;
}
}
}
dfs(1,1,0);
if(ans==INF)
{
printf("Impossible\n");
}
else
{
printf("%d\n",ans);
}
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int t = 1;
// int t;
// scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}
POJ2965 The Pilots Brothers’ refrigerator 搜索 +位运算
题目地址POJ2965 The Pilots Brothers’ refrigerator
题目大意:跟POJ1753基本是一样的,只是翻转的方法不同,这个每次翻转一行一列,必须结果全都是’-'符号,还要输出翻转的顺序。
思路:跟POJ1753是一样的,搜索遍历,用数组存储一下过程即可。不过我一开始是用stack存储的路径结果超时了。。。后面贴上我的超时代码。
AC代码:
#include <cstdio>
#include <cstdlib>
#include <stack>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int mm[5][5];
int ans=INF;
int xx[20],yy[20],ansx[20],ansy[20];
bool check()
{
for(int i = 1;i<=4;i++)
{
for(int j = 1;j<=4;j++)
{
if(mm[i][j])
{
return false;
}
}
}
return true;
}
void turn(int x, int y)
{
mm[x][y]^=1;
for(int i = 1;i <= 4;i++)
{
mm[x][i]^=1;
mm[i][y]^=1;
}
}
void dfs(int cnt, int x,int y)
{
if(check())
{
if(ans>cnt)
{
ans=cnt;
for(int i = 0;i < ans;i++)
{
ansx[i]=xx[i];
ansy[i]=yy[i];
}
}
return;
}
if(x==5)return;
turn(x,y);
xx[cnt]=x;
yy[cnt]=y;
if(y==4)
{
dfs(cnt+1,x+1,1);
}
else
{
dfs(cnt+1,x,y+1);
}
turn(x,y);
if(y==4)dfs(cnt,x+1,1);
else dfs(cnt,x,y+1);
}
void solve()
{
char ch;
for(int i = 1;i <= 4;i++)
{
for(int j = 1;j <= 4;j++)
{
scanf("%c",&ch);
while(ch!='-'&&ch!='+')
{
scanf("%c",&ch);
}
if(ch=='-')
mm[i][j]=0;
else
{
mm[i][j]=1;
}
}
}
dfs(0,1,1);
printf("%d\n",ans);
for(int i = 0;i < ans;i++)
{
printf("%d %d\n",ansx[i],ansy[i]);
}
}
int main()
{
int t = 1;
while(t--)
{
solve();
}
return 0;
}
超时代码:
#include <cstdio>
#include <cstdlib>
#include <stack>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
typedef pair<int,int> pii;
int mm[5][5];
int ans=INF;
stack<pii> s1;
bool check()
{
for(int i = 1;i<=4;i++)
{
for(int j = 1;j<=4;j++)
{
if(mm[i][j]==1)
{
return false;
}
}
}
return true;
}
void turn(int x, int y)
{
mm[x][y]^=1;
for(int i = 1;i <= 4;i++)
{
mm[x][i]^=1;
mm[i][y]^=1;
}
}
void dfs(int cnt, int x,int y,stack<pii> s)
{
if(check())
{
if(ans>cnt)
{
ans=cnt;
s1 = s;
return;
}
if(x==5)return;
turn(x,y);
s.push(make_pair(x,y));
if(y==4)
{
dfs(cnt+1,x+1,1,s);
}
else
{
dfs(cnt+1,x,y+1,s);
}
turn(x,y);
s.pop();
if(y==4)dfs(cnt,x+1,1,s);
else dfs(cnt,x,y+1,s);
}
void solve()
{
char ch;
for(int i = 1;i <= 4;i++)
{
for(int j = 1;j <= 4;j++)
{
scanf("%c",&ch);
while(ch!='-'&&ch!='+')
{
scanf("%c",&ch);
}
if(ch=='-')
mm[i][j]=0;
else
{
mm[i][j]=1;
}
}
}
stack<pii>s;
dfs(0,1,1,s);
printf("%d\n",ans);
while(!s.empty())
{
s.pop();
}
while(!s1.empty())
{
s.push(s1.top());
s1.pop();
}
while(!s.empty())
{
pii p = s.top();
printf("%d %d\n",p.first,p.second);
s.pop();
}
}
int main()
{
int t = 1;
while(t--)
{
solve();
}
return 0;
}
POJ1328 Radar Installation 思维+贪心
题目地址POJ1328 Radar Installation
题目大意:在一个二维坐标系中给出一些点坐标表示海岛的位置,雷达系统覆盖半径d,问最少需要多少个雷达系统可以覆盖所有岛屿。
思路:对于一个岛屿,能覆盖到它的雷达站的横坐标有一个范围,然后我们根据所有岛屿的坐标找到所有雷达站的范围,将雷达站的范围的左端点从左到右排序,将区间取交集,前面的交集跟后面的区间没有交集就说明必须要再新建一个雷达站。
我之前是想这直接将岛屿坐标从左到右进行排序,然后从左到右遍历点坐标,一旦一个点到当前圆心的距离大于d就新建一个雷达,但是这样做会忽略下面的情况。
c点本可以和d点共用一个雷达站,但是这样的算法导致多添加了一个雷达。
AC代码:
#include <cstdlib>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
typedef pair<double,double> pdd;
pdd a[1005];
int cnt;
void solve()
{
int n, d, maxy;//当时把maxy的初始化放在了这里,导致错了好几发,一直没找到问题所在。头都炸了。
while(scanf("%d%d",&n,&d)&&n)
{
maxy=0;
for(int i = 1;i <= n;i++)
{
int x, y;
scanf("%d%d",&x,&y);
maxy = max(maxy,y);
a[i].first = x-sqrt(d*d-y*y);
a[i].second = x+sqrt(d*d-y*y);
}
if(maxy>d)
{
printf("Case %d: -1\n",++cnt);
continue;
}
sort(a+1,a+1+n);
double r = a[1].second;
int ans=1;
for(int i = 1;i <= n;i++)
{
if(r < a[i].first)
{
ans++;
r = a[i].second;
}
else if(r > a[i].second)
{
r = a[i].second;
}
}
printf("Case %d: %d\n",++cnt,ans);
}
}
int main()
{
int t = 1;
while(t--)
{
solve();
}
return 0;
}
POJ2109 Power of Cryptography 库函数
题目地址POJ2109 Power of Cryptography
题目大意:输入两个整数
1
≤
p
≤
1
0
101
1\le p\le 10^{101}
1≤p≤10101,求出一个整数k使得
k
n
=
p
k
k^n=pk
kn=pk
思路:直接用库函数pow求解即可,double的范围可到300位
pow(a,b)表示
a
b
a^b
ab那么求a的开b次幂就是pow(a,1/b)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int main()
{
double a,b;
while(~scanf("%lf%lf",&a,&b))
{
printf("%.0f\n",pow(b,1.0/a));
}
return 0;
}
POJ2586 Y2K Accounting Bug
题目地址:Y2K Accounting Bug
题目大意:看不明白
思路:
POJ3295 Tautology 思维+计算模拟
题目地址POJ3295 Tautology
题目大意:输入由p、q、r、s、t、K、A、N、C、E共10个字母组成的逻辑表达式,
其中p、q、r、s、t的值为true或false,即逻辑变量;
K、A、N、C、E为逻辑运算符,
K and:x && y
A or:x || y
N not :! x
C implies 😦!x)||y
E equals :x==y
问这个逻辑表达式是否为永真式。
PS:输入格式保证是合法的
思路:
对于逻辑变量的每个取值,都依次枚举 判断对于每一种逻辑变量的取值情况表达式是否为真
#include<iostream>
using namespace std;
int cnt;
char str[101];
bool step(char str[101],int tk){
cnt++;
switch(str[cnt]){
case 'p':return tk&1;
case 'q':return(tk>>1)&1;
case 'r':return(tk>>2)&1;
case 's':return(tk>>3)&1;
case 't':return(tk>>4)&1;
case 'N':return !step(str,tk);
case 'K':return step(str,tk)&step(str,tk);
case 'A':return step(str,tk)|step(str,tk);
case 'C':return !step(str,tk)|step(str,tk);
case 'E':return step(str,tk)==step(str,tk);
}
}
bool judge(char str[101]){
for(int i=0;i<32;i++){
cnt=-1;
if(!step(str,i)) return 0;
}
return 1;
}
int main(){
while(cin>>str){
if(str[0]=='0') break;
if(judge(str))
cout<<"tautology"<<endl;
else
cout<<"not"<<endl;
}
return 0;
}
POJ1068 Parencodings 模拟+思维
题目地址POJ1068 Parencodings
题目大意:对于一个括号序列有两个数组,p数组表示的是第i个右括号左边的左括号数量。w数组表示的是第i个右括号所匹配的左括号之间有多少对括号加上自身。
思路:模拟,从第i个括号开始向左遍历,同时记录右括号的个数cnt,在左移的过程中减去两个右括号之间的左括号数,一旦cnt的值小于等于0就要停止并退出。
/*
**
*/
#include <iostream>
#include <cstdio>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int a[30],p[30],w[30];
void solve()
{
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++)
{
scanf("%d",a+i);
int t = 0;
for(int j = i;j>=1;j--)
{
t++;
t-=(a[j]-a[j-1]);
if(t<=0)
{
w[i]=i-j+1;
break;
}
}
printf("%d ",w[i]);
}
printf("\n");
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
// int t = 1;
int t;
scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}
POJ2632 Crashing Robots 模拟+思维
题目地址POJ2632 Crashing Robots
题目大意:给一个坐标系,给出每个机器人的初始位置和朝向,每个机器人有三种命令,左转,右转和前进,给出一个操作序列,操作序列格式为机器人编号,操作,操作次数,最后输出机器人是否撞墙或者撞到某个机器人。
思路:没什么技巧,就是直接模拟然后遍历判断即可,数据量比较小。
问题:交的时候居然编译错误,是因为map<char,pair<int,int> > movedir;
这一句,pair<>和map的>之间一定要有空格
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
char dir[4]={'N','W','S','E'};
map<char,pair<int,int> > movedir;
bool crash(int k,int n,int w,int h);
struct robot{
int x,y,k,num;
char direction;
bool mo(char t,int a,int n,int w, int h)
{
if(t=='L')
{
k+=a;
direction=dir[k%4];
}
else if(t=='R')
{
k-=a;
while(k<0)
{
k+=4;
}
direction=dir[k%4];
}
else
{
while(a--)
{
x+=movedir[direction].first;
y+=movedir[direction].second;
if(crash(num,n,w,h))
{
return true;
}
}
}
return false;
}
} robots[101];
bool crash(int k,int n,int w,int h)
{
if(robots[k].x>w||robots[k].y>h||robots[k].x<1||robots[k].y<1)
{
printf("Robot %d crashes into the wall\n",k);
return true;
}
for(int i = 1;i <= n;i++)
{
if(i==k)continue;
if(robots[k].x==robots[i].x&&robots[k].y==robots[i].y)
{
printf("Robot %d crashes into robot %d\n",k,i);
return true;
}
}
return false;
}
void init()
{
movedir['N']=make_pair(0,1);
movedir['W']=make_pair(-1,0);
movedir['S']=make_pair(0,-1);
movedir['E']=make_pair(1,0);
}
void solve()
{
int w,h;
scanf("%d%d",&w,&h);
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++)
{
scanf("%d%d %c",&robots[i].x,&robots[i].y,&robots[i].direction);
robots[i].num=i;
if(robots[i].direction=='N')
{
robots[i].k=0;
}
else if(robots[i].direction=='W')
{
robots[i].k=1;
}
else if(robots[i].direction=='S')
{
robots[i].k=2;
}
else
{
robots[i].k=3;
}
}
int flag=0;
for(int i = 1;i <= m;i++)
{
int num,t;
char action;
scanf("%d %c%d",&num,&action,&t);
if(!flag)
{
if(robots[num].mo(action,t,n,w,h))
{
flag=1;
// return;
}
}
}
if(!flag)
{
printf("OK\n");
}
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
// int t = 1;
int t;
scanf("%d",&t);
init();
while(t--)
{
solve();
}
return 0;
}
POJ1573 Robot Motion 模拟+思维
题目地址POJ1573 Robot Motion
题目大意:给一个矩阵,矩阵上每一个位置都以一个命令字符,EWSN,分别表示向东西南北移动,机器人从一个起始位置出发,问最后多少步后会走出地图,或者是多少步后会进入一个多少步的循环。
思路:也就是模拟,然后计数即可。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#define ll long long
using namespace std;
char mm[20][20];
bool vis[20][20];
map<char,pair<int,int> > movedir;
void init()
{
movedir['W']=make_pair(0,-1);
movedir['N']=make_pair(-1,0);
movedir['E']=make_pair(0,1);
movedir['S']=make_pair(1,0);
}
void countstep(int x,int y,int col)
{
int ans1=0,ans2=1;
int xx=1,yy=col;
int tx = xx,ty=yy;
while(xx!=x||yy!=y)
{
tx = xx,ty=yy;
ans1++;
xx+=movedir[mm[tx][ty]].first;
yy+=movedir[mm[tx][ty]].second;
}
tx = xx,ty=yy;
xx+=movedir[mm[tx][ty]].first;
yy+=movedir[mm[tx][ty]].second;
while(xx!=x||yy!=y)
{
tx = xx,ty=yy;
ans2++;
xx+=movedir[mm[tx][ty]].first;
yy+=movedir[mm[tx][ty]].second;
}
printf("%d step(s) before a loop of %d step(s)\n",ans1,ans2);
}
void solve()
{
int n,m,col;
while(scanf("%d%d%d",&n,&m,&col)&&n)
{
char ch;
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= m;j++)
{
scanf("%c",&ch);
while(ch=='\n') scanf("%c",&ch);
mm[i][j]=ch;
}
}
int x=1,y=col;
int ans = 0;
int flag=0;
while(!vis[x][y])
{
int tx = x,ty =y;
vis[x][y]=1;
ans++;
x+=movedir[mm[tx][ty]].first;
y+=movedir[mm[tx][ty]].second;
if(x>n||y>m||x<1||y<1)
{
flag=1;
printf("%d step(s) to exit\n",ans);
break;
}
}
if(!flag)
{
countstep(x,y,col);
}
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= m;j++)
{
vis[i][j]=false;
}
}
}
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int t = 1;
// int t;
// scanf("%d",&t);
init();
while(t--)
{
solve();
}
return 0;
}
POJ2996 Help Me with the Game 模拟+坐标变换
题目地址POJ2996 Help Me with the Game
题目大意:一个棋盘模拟,关键就是坐标变换比较麻烦。
输出时的条件:
不论黑白,KQRBN P均是依次输出,强制大写,但不输出“P”,只输出其坐标
对白棋的位置,小行优先大行输出(行的数字越小则优先)同行则按列的顺序(a~h)
对黑棋的位置,大行优先小行输出(行的数字越大则优先)同行则按列的顺序(a~h)
最后的棋子后面不带逗号,要找出最后的棋子’
思路:模拟即可,关键是找到每个棋子的坐标
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
char chessboard[20][40];
char chess[9][9];
string wres[40];
string bres[40];
int wcnt,bcnt;
void getpos(char ch)
{
if(ch>='a'&&ch<='z')
{
for(int i = 1;i <= 8;i++)
{
for(int j = 1;j <= 8;j++)
{
if(chess[i][j]==ch)
{
if(ch!='p')
{
bres[++bcnt]+=(ch-32);
bres[bcnt]+=('a'+j-1);
bres[bcnt]+=('0'+9-i);
}
else
{
bres[++bcnt]+=('a'+j-1);
bres[bcnt]+=('0'+9-i);
}
}
}
}
}
if(ch>='A'&&ch<='Z')
{
for(int i = 8;i >= 1;i--)
{
for(int j = 1;j <= 8;j++)
{
if(chess[i][j]==ch)
{
if(ch!='P')
{
wres[++wcnt]+=ch;
wres[wcnt]+=('a'+j-1);
wres[wcnt]+=('0'+9-i);
}
else
{
wres[++wcnt]+=('a'+j-1);
wres[wcnt]+=('0'+9-i);
}
}
}
}
}
}
void solve()
{
for(int i = 1;i <= 17;i++)
{
scanf("%s",chessboard[i]);
}
for(int i = 1;i <= 8;i++)
{
for(int j = 1;j <= 8;j++)
{
chess[i][j]=chessboard[2*i][4*j-2];
}
}
getpos('K');
getpos('Q');
getpos('R');
getpos('B');
getpos('N');
getpos('P');
printf("White: ");
for(int i = 1;i <= wcnt;i++)
{
cout << wres[i];
if(i<wcnt)
printf(",");
}
printf("\n");
getpos('k');
getpos('q');
getpos('r');
getpos('b');
getpos('n');
getpos('p');
printf("Black: ");
for(int i = 1;i <= bcnt;i++)
{
cout << bres[i];
if(i<bcnt)
printf(",");
}
printf("\n");
}
int main()
{
int t = 1;
while(t--)
{
solve();
}
return 0;
}
POJ2993 Emag eht htiw Em Pleh 模拟+坐标变换
题目地址POJ2993 Emag eht htiw Em Pleh
题目大意:跟POJ2996一样,只是输入输出反了
思路:还是模拟,主要是坐标的变换
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
string chessboard[40];
string wchess[40];
string bchess[40];
int wcnt,bcnt;
void init()
{
chessboard[1]="+---+---+---+---+---+---+---+---+";
chessboard[2]="|...|:::|...|:::|...|:::|...|:::|";
chessboard[3]="+---+---+---+---+---+---+---+---+";
chessboard[4]="|:::|...|:::|...|:::|...|:::|...|";
chessboard[5]="+---+---+---+---+---+---+---+---+";
chessboard[6]="|...|:::|...|:::|...|:::|...|:::|";
chessboard[7]="+---+---+---+---+---+---+---+---+";
chessboard[8]="|:::|...|:::|...|:::|...|:::|...|";
chessboard[9]="+---+---+---+---+---+---+---+---+";
chessboard[10]="|...|:::|...|:::|...|:::|...|:::|";
chessboard[11]="+---+---+---+---+---+---+---+---+";
chessboard[12]="|:::|...|:::|...|:::|...|:::|...|";
chessboard[13]="+---+---+---+---+---+---+---+---+";
chessboard[14]="|...|:::|...|:::|...|:::|...|:::|";
chessboard[15]="+---+---+---+---+---+---+---+---+";
chessboard[16]="|:::|...|:::|...|:::|...|:::|...|";
chessboard[17]="+---+---+---+---+---+---+---+---+";
}
void putchess()
{
int row,col;
for(int i = 0;i < wcnt;i++)
{
if(wchess[i].size()==3)
{
col = wchess[i][1]-'a'+1;
col= col*4-2;
row = '9'-wchess[i][2];
row*=2;
chessboard[row][col]=wchess[i][0];
}
else if(wchess[i].size()==2)
{
col = wchess[i][0]-'a'+1;
col= col*4-2;
row = '9'-wchess[i][1];
row*=2;
chessboard[row][col]='P';
}
}
for(int i = 0;i < bcnt;i++)
{
if(bchess[i].size()==3)
{
col = bchess[i][1]-'a'+1;
col= col*4-2;
row = '9'-bchess[i][2];
row*=2;
chessboard[row][col]=bchess[i][0]+32;
}
else if(wchess[i].size()==2)
{
col = bchess[i][0]-'a'+1;
col= col*4-2;
row = '9'-bchess[i][1];
row*=2;
chessboard[row][col]='p';
}
}
for(int i = 1;i <= 17;i++)
{
cout << chessboard[i] << endl;
}
}
void solve()
{
char ch;
string str;
cin >> str;
scanf("%c",&ch);
while(ch!='\n')
{
scanf("%c",&ch);
while(ch!=','&&ch!='\n')
{
wchess[wcnt]+=ch;
scanf("%c",&ch);
}
wcnt++;
}
cin >> str;
scanf("%c",&ch);
while(ch!='\n')
{
scanf("%c",&ch);
while(ch!=','&&ch!='\n')
{
bchess[bcnt]+=ch;
scanf("%c",&ch);
}
bcnt++;
}
putchess();
}
int main()
{
int t = 1;
init();
while(t--)
{
solve();
}
return 0;
}