考验编码能力的一场比赛。
C是水题,就是矩阵变化,自己转置几次就能发现规律
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
using namespace std;
int a[41][41],b[41][41];
int main()
{
int n,m;
while(~scanf("%d",&n) && n){
int cnt=0;int ans=0;int tmp=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",a[i]+j);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
scanf("%d",b[i]+j);
if(b[i][j]==a[i][j]) tmp++;
}
ans=max(ans,tmp);
cnt=tmp=0;
for(int j=n-1;j>=0;j--)
for(int i=0;i<n;i++,cnt++)
{
///a[i][j]=a[cnt/n][cnt%n];
if(b[i][j]==a[cnt/n][cnt%n])
tmp++;
}
ans=max(ans,tmp);
cnt=tmp=0;
for(int i=n-1;i>=0;i--)
for(int j=n-1;j>=0;j--,cnt++)
{
/// a[i][j]=a[cnt/n][cnt%n];
if(b[i][j]==a[cnt/n][cnt%n])
tmp++;
}
ans=max(ans,tmp);
cnt=tmp=0;
for(int j=0;j<n;j++)
for(int i=n-1;i>=0;i--,cnt++)
{
/// a[i][j]=a[cnt/n][cnt%n];
if(b[i][j]==a[cnt/n][cnt%n])
tmp++;
}
ans=max(ans,tmp);
cout<<ans<<endl;
}
return 0;
}
多目的地的最短路径,可以走回头路
B题,好久没写搜索了,求最短路径。跟队友思考后决定用next_permutation函数来枚举情况组合情况。因为常规的状态记录不能走回头路。而且我们傻叉的也没有标记走过的路线。 状态啊状态。dp[110][110][32] 记录状态。 重新写了下。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cstdio>
#define inf 0x3f3f3f3f
using namespace std;
int n,m,k;
int dp[110][110][1<<5];
char G[110][110];
int dr[]={-1,0,1,0},dc[]={0,1,0,-1};
struct P
{
int r,c,s;
}in,tmp,s,dist[5];
int bfs()
{
queue<struct P> q;
s.s=0;
for(int i=0;i<k;i++)
if(s.r==dist[i].r && s.c==dist[i].c)
s.s|=1<<i;
q.push(s);
memset(dp,0x3f,sizeof(dp));
dp[s.r][s.c][s.s]=0;
while(q.size()){
tmp=q.front();q.pop();
if(tmp.s==(1<<k)-1)
return dp[tmp.r][tmp.c][tmp.s];
for(int i=0;i<4;i++){
int ss=tmp.s;
int rr=tmp.r+dr[i];
int cc=tmp.c+dc[i];
if(rr<0 || rr>=n || cc<0 || cc>=m || G[rr][cc]=='#') continue;
if(G[rr][cc]=='!')
for(int i=0;i<k;i++)
if(dist[i].r==rr && dist[i].c==cc){
ss|=1<<i;break;
}
if(dp[rr][cc][ss]!=inf) continue;
dp[rr][cc][ss]=dp[tmp.r][tmp.c][tmp.s]+1;
in.r=rr;in.s=ss;in.c=cc;
q.push(in);
}
}
return -1;
}
int main()
{
while(scanf("%d%d",&n,&m) && n+m ){
for(int i=0;i<n;i++){
getchar();
for(int j=0;j<m;j++){
scanf("%c",G[i]+j);
if(G[i][j]=='@')
s.r=i,s.c=j;
}
}
scanf("%d",&k);int r,c;
for(int i=0;i<k;i++){
scanf("%d%d",&r,&c);r--,c--;
G[r][c]='!';
dist[i].r=r;dist[i].c=c;
}
cout<<bfs()<<endl;
}
return 0;
}
A
这个题裸状压,思路就是枚举可以放灯的点,如果被照射了就继续,要注意范围外也可以被照射到。直接枚举放的状态。
刚开始用dfs写,怎么都有问题,调了好久,我傻逼的以为过程中要标记覆盖的点,也不知道那里的细节没处理好。WA,后来不覆盖了就AC,
dfs:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#define inf 0x3f3f3f3f
using namespace std;
int n,m,k;int ans;
char G[210][210];
int dr[]={-1,0,1,0},dc[]={0,1,0,-1};
int asdf;
struct P
{
int r,c,cnt;
}dist[20];
int In(int r,int c)
{
if(r<=0 || r>n || c<=0 || c>m) return 0;
return 1;
}
void dfs(int s,int p,int num,int tag)
{
struct P t1,t2;
if(p==k){
if(s==(1<<k)-1)
ans=min(ans,num);
return;
}
dfs(s,p+1,num,tag);
for(int i=0;i<4;i++){
if(tag==1 && i>0) break;
t1.r=dist[p].r+dr[i];t1.c=dist[p].c+dc[i];
t2.r=dist[p].r+dr[(i+1)%4];t2.c=dist[p].c+dc[(i+1)%4];
if( G[t1.r][t1.c]!='#' && G[t2.r][t2.c]!='#')
{
int t=s;int tg;
if(i==0) tg=tag;
else tg=1;
t|=1<<(G[dist[p].r][dist[p].c]-'a');
if (In(t1.r,t1.c)) t|=1<<(G[t1.r][t1.c]-'a');
if (In(t2.r,t2.c)) t|=1<<(G[t2.r][t2.c]-'a');
dfs(t,p+1,num+1,tg);
}
}
}
int main()
{
while(scanf("%d%d",&n,&m) && n+m ){
memset(G,0,sizeof(G));
k=0;ans=inf;
for(int i=1;i<=n;i++){
getchar();
for(int j=1;j<=m;j++){
scanf("%c",G[i]+j);
if(G[i][j]=='.')
G[i][j]='a'+k, dist[k].r=i, dist[k].c=j, dist[k].cnt=k++;
}
}
dfs(0,0,0,0);
if(ans==inf) ans=-1;
cout<<ans<<endl;
}
return 0;
}
二进制枚举:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cstdio>
#define inf 0x3f3f3f3f
using namespace std;
int n,m,k;int ans;
char G[210][210];
int dr[]={-1,0,1,0},dc[]={0,1,0,-1};
struct P
{
int r,c,cnt;
}dist[20];
int In(int r,int c)
{
if(r<=0 || r>n || c<=0 || c>m) return 0;
return 1;
}
int cntbit(int x)
{
int res=0;
for(int i=0;i<30;i++)
if( (1<<i) & x ) res++;
return res;
}
int main()
{
while(scanf("%d%d",&n,&m) && n+m ){
k=0;ans=inf;memset(G,0,sizeof(G));
for(int i=1;i<=n;i++){
getchar();
for(int j=1;j<=m;j++){
scanf("%c",G[i]+j);
if(G[i][j]=='.')
G[i][j]='a'+k, dist[k].r=i, dist[k].c=j, dist[k].cnt=k++;
}
}
if(k==0){puts("0");continue;}
int rt=1<<k;int mm=0;
for(int i=5;i<15;i++)
mm+=1<<i;
for(int s=1;s<rt;s++){/// menu state
int tag=0;
if(s==mm-1)
continue;
for(int sp=0;(1<<sp)<=s;sp++){/// memu special point
if(((1<<sp)&s)==0) continue;
int fins=s;
for(int i=0;(1<<i)<=s;i++){
if((1<<i) &s ){
if(i!=sp){
int r=dist[i].r;
int c=dist[i].c;
if(G[r-1][c]=='#' || G[r][c+1]=='#') {tag=1;break;}/// this logic
if(G[r][c+1]) fins|=1<<(G[r][c+1]-'a');
if(G[r-1][c]) fins|=1<<(G[r-1][c]-'a');
}
}
}
if(tag) {tag=0;continue;}///break ? continue ///
for(int i=0;i<4;i++){
int finstate=fins;
int r=dist[sp].r+dr[i];
int c=dist[sp].c+dc[i];
int rr=dist[sp].r+dr[(i+1)%4];
int cc=dist[sp].c+dc[(i+1)%4];
if(G[r][c]=='#' || G[rr][cc]=='#') continue;
if(G[r][c]) finstate|=1<<(G[r][c]-'a');
if(G[rr][cc]) finstate|=1<<(G[rr][cc]-'a');
if(finstate==rt-1)
{ans=min(ans,cntbit(s));tag=1;break;}
}
if(tag) break;
}
}
if(ans==inf) ans=-1;
cout<<ans<<endl;
}
return 0;
}