POJ分类一.基本算法
https://vjudge.net/article/6

1.枚举
POJ-1753
题意:4X4枚正反面的硬币 任意翻 翻成同一面最小步数
翻一枚 上下左右全翻
思路:枚举 第一行 0000~1111 16种翻法 因为下一行总能把上一行翻成同一面 用下一行控制上一行 看最后一行满足不满足条件 更新最小值
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <utility>
#include <map>
#include <vector>
#include <queue>
using namespace std;
const int N=10;
char g[N][N],back[N][N];
void turn(int x,int y)
{
if(g[x][y]=='b')g[x][y]='w';
else g[x][y]='b';
int dx[4]={0,-1,0,1},dy[4]={-1,0,1,0};
for(int i=0;i<4;i++)
{
int nx=dx[i]+x,ny=y+dy[i];
if(nx>=0&&nx<=3&&ny>=0&&ny<=3)
{
if(g[nx][ny]=='b')g[nx][ny]='w';
else g[nx][ny]='b';
}
}
}
int work()
{
int ans=1e9;
memcpy(back,g,sizeof g);
for(int k=0;k<1<<4;k++)//枚举第一行所有可能按的方式 w->b
{
int res=0;
for(int j=0;j<4;j++)
if(k>>j&1)res++,turn(0,j);
for(int i=0;i<3;i++)
for(int j=0;j<4;j++)
if(g[i][j]=='w') turn(i+1,j), res++;
bool flag=true;
for(int j=0;j<4;j++)
if(g[3][j]=='w')flag=false;
if(flag)ans=min(ans,res);
memcpy(g,back,sizeof back);
}
for(int k=0;k<1<<4;k++)//枚举第一行所有可能按的方式
{
int res=0;
for(int j=0;j<4;j++)
if(k>>j&1) res++,turn(0,j);
for(int i=0;i<3;i++)
for(int j=0;j<4;j++)
if(g[i][j]=='b')turn(i+1,j),res++;
bool flag=true;
for(int j=0;j<4;j++)
if(g[3][j]=='b')flag=false;
if(flag)ans=min(ans,res);
memcpy(g,back,sizeof back);
}
return ans;
}
void solve()
{
for(int i=0;i<4;i++)cin>>g[i];
int t=work();
if(t==1e9)cout<<"Impossible"<<endl;
else cout<<t<<endl;
}
int main()
{
int tests=1;
while(tests--)
{
solve();
}
return 0;
}
POJ-2965
题意:与上题区别是 动一个 同行同列全翻
思路:枚举每一行16种选择 使用位运算 0表示开 1表示关 如果当前状态是0则表示冰箱门全开了
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <iostream>
#include <utility>
#include <vector>
#include <cmath>
#define fi first
#define sc second
using namespace std;
typedef long long LL;
typedef pair<int,int>PII;
const int N=10;
int a[N],state=0,res=0,minn=1e9;
char g[N][N];
void turn(int x,int y)
{
for(int i=x*4-1;i>=4*(x-1);i--)state^= 1<<i;
for(int i=y-1;i<=15;i+=4)state^= 1<<i;
state^= (1<<(y-1+(x-1)*4));
}
vector <int>temp[N],ans[N];
void dfs(int x)
{
if(x==5)
{
if(state==0)
{
if (minn>res)
{
minn=res;
for(int i=1;i<=4;i++)
{
ans[i].clear();
for(int j=0;j<temp[i].size();j++)ans[i].push_back(temp[i][j]);
}
}
}
return ;
}
int backup=res,b1=state;
for(int i=0;i<1<<4;i++)
{
for(int j=0;j<=3;j++)
{
if(i>>j&1)
{
res++;
turn (x,j+1);
temp[x].push_back(j+1);
}
}
dfs(x+1);
res=backup;
temp[x].clear();
state=b1;
}
}
void solve()
{
for(int i=0;i<=3;i++)
{
scanf("%s",&g[i]);
for(int j=0;j<=3;j++)if(g[i][j]=='+')state+= (1<<(i*4+j));
}
dfs(1);
printf("%d\n",minn);
for(int i=1;i<=4;i++)
for(int j=0;j<ans[i].size();j++)
printf("%d %d\n",i,ans[i][j]);
puts("");
}
int main()
{
int tests=1;
//scanf("%d",&tests);
while(tests--)
{
solve();
}
return 0;
}
2.贪心
POJ-1328
每个岛的极限位置建雷达站 排序 如果y轴上大于雷达范围 就输出-1
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <iostream>
#include <utility>
#include <vector>
#include <cmath>
#define fi first
#define sc second
using namespace std;
const int N=1e3+10;
typedef long long LL;
typedef pair<double,double>PDD;
int n,d;
PDD q[N];
int tt=0;
int cmp(PDD A,PDD B)
{
double r1=A.fi+sqrt(d*d-A.sc*A.sc);
double r2=B.fi+sqrt(d*d-B.sc*B.sc);
return r1<r2;
}
void solve()
{
bool flag=false;int ans=1;
for(int i=0;i<n;i++)
{
double x,y;scanf("%lf %lf",&x,&y);
q[i]=make_pair(x,y);
if(y>d)flag=true;
}
printf("Case %d: ",++tt);
if(flag)
{
printf("-1\n");return;
}
sort(q,q+n,cmp);
double last=(q[0].fi+sqrt(d*d-q[0].sc*q[0].sc));
for(int i=1;i<n;i++)
{
double x=last-q[i].fi,y=q[i].sc;
if(x*x+y*y>d*d)
{
ans++;
last=(q[i].fi+sqrt(d*d-q[i].sc*q[i].sc));
}
}
printf("%d\n",ans);
}
int main()
{
int tests;
//scanf("%d",&tests);zcin.tie(0);
//ios::sync_with_stdio(0);cin.tie(0);
while(scanf("%d%d",&n,&d),n||d)
//while(tests--)
{
solve();
}
return 0;
}
POJ-2109
k的n次方等于p 给n,p求k (1<=n<= 200, 1<=p<1e101)
直接输出p的n分之一次方 因为double可以取到1e308
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <iostream>
#include <utility>
#include <vector>
#include <cmath>
#define fi first
#define sc second
using namespace std;
typedef long long LL;
double n,p;
void solve()
{
printf("%.0f\n",pow(p,1.0/n));
}
int main()
{
int tests;
//scanf("%d",&tests);zcin.tie(0);
//ios::sync_with_stdio(0);cin.tie(0);
while(~scanf("%lf%lf",&n,&p))
//while(tests--)
{
solve();
}
return 0;
}
POJ-2586
题目说每连续5个月的报表都显示亏损了(共8个 如1到5 8到12) 问整年最大的盈余是多少
思路:比较月盈余s与月亏损d 5个里面选最少个d让连续5月都亏损
d s
4s<d 2 10
3s<2d 4 8
2s<3d 6 6
s<4d 9 3 (补个12)
5d 12 0
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <iostream>
#include <utility>
#include <vector>
#include <cmath>
#define fi first
#define sc second
using namespace std;
typedef long long LL;
LL s,d;
void solve()
{
LL delta,beishu=0;
for(int i=1;i<=5;i++)
{
if(s*(5-i)-d*i<0)
{
beishu=(5-i);
break;
}
}
if(beishu>=2)delta=(2+beishu*2)*s-(12-2-beishu*2)*d;
else if(beishu==1)delta=3*s-9*d;
else delta=-12*d;
if(delta<=0)puts("Deficit");
else printf("%lld\n",delta);
}
int main()
{
int tests;
//scanf("%d",&tests);zcin.tie(0);
//ios::sync_with_stdio(0);cin.tie(0);
while(~scanf("%lld%lld",&s,&d))
//while(tests--)
{
solve();
}
return 0;
}
5.构造法
POJ-3295
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <iostream>
#include <utility>
#include <vector>
#include <cmath>
#define fi first
#define sc second
using namespace std;
typedef long long LL;
typedef pair<int,int>PII;
const int N=110;
char str[N];
int p,q,r,s,t;
int a[N],hh=0;
void check()
{
int len=strlen(str);
for(int i=len-1;i>=0;i--)
{
if(str[i]=='p')a[++hh]=p;
if(str[i]=='q')a[++hh]=q;
if(str[i]=='r')a[++hh]=r;
if(str[i]=='s')a[++hh]=s;
if(str[i]=='t')a[++hh]=t;
if(str[i]=='K')
{
int t1=a[hh],t2=a[--hh];
a[hh]=t1&&t2;
}
if(str[i]=='A')
{
int t1=a[hh],t2=a[--hh];
a[hh]=t1||t2;
}
if(str[i]=='N')
{
a[hh]=!a[hh];
}
if(str[i]=='C')
{
int t1=a[hh],t2=a[--hh];
if(t1==0&&t2==1)a[hh]=0;
else a[hh]=1;
}
if(str[i]=='E')
{
int t1=a[hh],t2=a[--hh];
a[hh]=(t1==t2);
}
}
}
void solve()
{
for( p=0;p<2;p++)
{
for( q=0;q<2;q++)
{
for( r=0;r<2;r++)
{
for( s=0;s<2;s++)
{
for( t=0;t<2;t++)
{
hh=0;
check();
if(a[1]==0)
{
puts("not");
return ;
}
}
}
}
}
}
puts("tautology");
}
int main()
{
int tests=1;
//scanf("%d",&tests);
while(~scanf("%s",&str),str[0]!='0')
{
solve();
}
return 0;
}
6.模拟法
POJ-1068
数据量小 直接还原出原字符串 再按照题意模拟
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <iostream>
#include <utility>
#include <vector>
#include <cmath>
#define fi first
#define sc second
using namespace std;
typedef long long LL;
const int N=2e5+10;
int a[N];
bool flag[N];
void solve()
{
vector <char>v;
int n;scanf("%d",&n);
int last=0;
for(int i=1;i<=n;i++)
{
int x;scanf("%d",&x);
if(x>last)
{
for(int j=1;j<=x-last;j++)v.push_back('(');
last=x;
}
v.push_back(')');
}
memset(flag,0,sizeof flag);
for(int i=0;i<v.size();i++)
{
if(v[i]==')')
{
int num=0;
for(int j=i;j>=0;j--)
{
if(v[j]=='(')
{
num++;
}
if(flag[j]==false&&v[j]=='(')
{
flag[j]=true;
printf("%d ",num);
break;
}
}
}
}
puts("");
}
int main()
{
int tests;
scanf("%d",&tests);
//ios::sync_with_stdio(0);cin.tie(0);
//while(~scanf("%lld%lld",&s,&d))
while(tests--)
{
solve();
}
return 0;
}
POJ-2632
模拟
注意负数的模运算 要加mod
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <iostream>
#include <utility>
#include <vector>
#include <cmath>
#define fi first
#define sc second
using namespace std;
typedef long long LL;
typedef pair<int,int>PII;
const int N=110;
PII q[N];
int n,m,a,b;int ne[N];
int dx[4]={-1,0,1,0},dy[4]={0,-1,0,1};// w s e n
void solve()
{
scanf("%d %d",&a,&b);
scanf("%d %d",&n,&m);//b hang a lie
for(int i=1;i<=n;i++)
{
int x,y;char c;
scanf("%d %d %c",&x,&y,&c);
q[i]=make_pair(x,y);
if(c=='W')ne[i]=0;
if(c=='S')ne[i]=1;
if(c=='E')ne[i]=2;
if(c=='N')ne[i]=3;
}
int flag=0,l1,l2;
while(m--)
{
int x;char op ;int t;
scanf("%d %c %d",&x,&op,&t);
if(flag)continue;
if(op=='F')
{
int y=ne[x];
//q[i].fi+=dx[y]*t,q[i].sc+=dy[y]*t;
for(int i=1;i<=t;i++)
{
q[x].fi+=dx[y],q[x].sc+=dy[y];
for(int j=1;j<=n;j++)
{
if(j==x)continue;
if(q[x].fi==q[j].fi&&q[x].sc==q[j].sc)
{
l1=x,l2=j;
flag=1;break;
}
}
if(q[x].fi>a||q[x].fi<1||q[x].sc>b||q[x].sc<1)
{
flag=2;
l1=x;
break;
}
if(flag)break;
}
}
else if(op=='L')
{
ne[x]=(ne[x]+t%4)%4;
}
else
{
ne[x]=(4+ne[x]-t%4)%4;
}
}
if(flag==1)
{
printf("Robot %d crashes into robot %d\n",l1,l2);
}
if(flag==2)printf("Robot %d crashes into the wall\n",l1);
if(!flag)puts("OK");
}
int main()
{
int tests;
scanf("%d",&tests);
while(tests--)
{
solve();
}
return 0;
}
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <iostream>
#include <utility>
#include <vector>
#include <cmath>
#define fi first
#define sc second
using namespace std;
typedef long long LL;
typedef pair<int,int>PII;
const int N=20;
int n,m,c,step=0;
char g[N][N];
int flag[N][N];
bool ok=false;
void dfs(int x,int y)
{
if(ok)return ;
if(flag[x][y])
{
int l2=step-flag[x][y]+1;
printf("%d step(s) before a loop of %d step(s)\n",flag[x][y]-1,l2);
ok=true;
}
if(x<0||x>=n||y<0||y>=m)
{
printf("%d step(s) to exit\n",step);
ok=true;
}
flag[x][y]=++step;
if(g[x][y]=='E')dfs(x,y+1);
if(g[x][y]=='W')dfs(x,y-1);
if(g[x][y]=='N')dfs(x-1,y);
if(g[x][y]=='S')dfs(x+1,y);
}
void solve()
{
ok=false;step=0;memset(flag,0,sizeof flag);
for(int i=0;i<n;i++)
{
scanf("%s",&g[i]);
//printf("%s\n",g[i]);
}
dfs(0,c-1);
}
int main()
{
int tests;
//scanf("%d",&tests);
while(scanf("%d%d%d",&n,&m,&c),n&&m&&c)
{
solve();
}
return 0;
}

浙公网安备 33010602011771号