2013 Asia Hangzhou Regional Contest

Lights Against Dudely http://acm.hdu.edu.cn/showproblem.php?pid=4770

15个位置,所以可以暴力枚举那些放,对于放的再暴力枚举哪个转,对于转的,再枚举转哪个方向。选位置放我用了2进制枚举,选出哪个转和枚举4个方向for循环就行。可以加个小剪枝。  

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define mt(a,b) memset(a,b,sizeof(a))
  5 using namespace std;
  6 const int inf=0x3f3f3f3f;
  7 const int M=256;
  8 char a[M][M];
  9 struct point{
 10     int x,y;
 11     friend bool operator ==(const point &a,const point &b){
 12         return a.x==b.x&&a.y==b.y;
 13     }
 14 }p[16];
 15 bool vis[16];
 16 int dx[]={-1,0,1,0};
 17 int dy[]={0,1,0,-1};
 18 int n,m,len,useid[16];
 19 bool isjing(const int &x,const int &y){
 20     if(x>=0&&x<n&&y>=0&&y<m&&a[x][y]=='#') return true; return false;
 21 }
 22 bool flag(const point &b){
 23     if(isjing(b.x,b.y)) return false;
 24     for(int i=0;i<len;i++){
 25         if(b==p[i]){
 26             vis[i]=true;
 27             break;
 28         }
 29     }
 30     return true;
 31 }
 32 void step(point &pp,const int &dir){
 33     pp.x+=dx[dir];
 34     pp.y+=dy[dir];
 35 }
 36 bool cover(const point &pp,const int &dir){
 37     if(!flag(pp)) return false;
 38     point qq=pp;
 39     step(qq,dir);
 40     if(!flag(qq)) return false;
 41     qq=pp;
 42     step(qq,(dir+1)%4);
 43     if(!flag(qq)) return false;
 44     return true;
 45 }
 46 int main(){
 47     while(~scanf("%d%d",&n,&m),n|m){
 48         for(int i=0;i<n;i++){
 49             scanf("%s",a[i]);
 50         }
 51         len=0;
 52         for(int i=0;i<n;i++){
 53             for(int j=0;j<m;j++){
 54                 if(a[i][j]=='.'){
 55                     p[len].x=i;
 56                     p[len].y=j;
 57                     len++;
 58                 }
 59             }
 60         }
 61         int all=1<<len,ans=inf;
 62         for(int i=0;i<all;i++){
 63             if(len==0) ans=0;
 64             int lu=0;
 65             for(int j=0;j<len;j++){
 66                 if((i>>j)&1) useid[lu++]=j;
 67             }
 68             if(ans<=lu) continue;
 69             for(int j=0;j<lu;j++){
 70                 for(int dir=0;dir<4;dir++){
 71                     mt(vis,0);
 72                     bool ok=true;
 73                     for(int k=0;k<lu;k++){
 74                         if(k!=j){
 75                             if(!cover(p[useid[k]],0)){
 76                                 ok=false;
 77                                 break;
 78                             }
 79                         }
 80                         else{
 81                             if(!cover(p[useid[k]],dir)){
 82                                 ok=false;
 83                                 break;
 84                             }
 85                         }
 86                     }
 87                     if(ok){
 88                         bool cc=true;
 89                         for(int j=0;j<len;j++){
 90                             if(!vis[j]){
 91                                 cc=false;
 92                                 break;
 93                             }
 94                         }
 95                         if(cc){
 96                             ans=min(ans,lu);
 97                         }
 98                     }
 99                 }
100             }
101         }
102         if(ans==inf) ans=-1;
103         printf("%d\n",ans);
104     }
105     return 0;
106 }
View Code

 

 

hdu 4771 http://acm.hdu.edu.cn/showproblem.php?pid=4771

bfs基础,重复状态的判断,二进制表示不同状态。题意有k个物品在图中,问最少几步全部拿到。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 #define mt(a,b) memset(a,b,sizeof(a))
 5 using namespace std;
 6 const int M=128;
 7 char a[M][M];
 8 int pp[M][M];
 9 bool vis[M][M][32];
10 int n,m,sx,sy,k;
11 struct Q{
12     int x,y,sta,step;
13 }now,pre;
14 queue<Q> q;
15 int dx[]={0,0,1,-1};
16 int dy[]={1,-1,0,0};
17 int bfs(){
18     now.x=sx;
19     now.y=sy;
20     now.sta=pp[sx][sy];
21     now.step=0;
22     mt(vis,0);
23     vis[sx][sy][now.sta]=true;
24     while(!q.empty()) q.pop();
25     q.push(now);
26     while(!q.empty()){
27         pre=q.front();
28         q.pop();
29         if(pre.sta==(1<<k)-1) return pre.step;
30         for(int i=0;i<4;i++){
31             int tx=pre.x+dx[i];
32             int ty=pre.y+dy[i];
33             if(tx>=0&&tx<n&&ty>=0&&ty<m&&a[tx][ty]!='#'&&!vis[tx][ty][pre.sta]){
34                 now.x=tx;
35                 now.y=ty;
36                 now.sta=pre.sta|pp[tx][ty];
37                 now.step=pre.step+1;
38                 vis[tx][ty][now.sta]=true;
39                 q.push(now);
40             }
41         }
42     }
43     return -1;
44 }
45 int main(){
46     while(~scanf("%d%d",&n,&m),n|m){
47         for(int i=0;i<n;i++){
48             scanf("%s",a[i]);
49             for(int j=0;j<m;j++){
50                 if(a[i][j]=='@'){
51                     sx=i;
52                     sy=j;
53                 }
54             }
55         }
56         mt(pp,0);
57         scanf("%d",&k);
58         for(int i=0,x,y;i<k;i++){
59             scanf("%d%d",&x,&y);
60             pp[x-1][y-1]|=(1<<i);
61         }
62         printf("%d\n",bfs());
63     }
64     return 0;
65 }
View Code

 

hdu 4772 Zhuge Liang's Password http://acm.hdu.edu.cn/showproblem.php?pid=4772

矩阵转4次,看哪次相等的最多。

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int M=32;
 5 int a[M][M],b[M][M],c[M][M],n;
 6 int solve(){
 7     for(int i=1;i<=n;i++){
 8         for(int j=1;j<=n;j++){
 9             c[n-j+1][i]=a[i][j];
10         }
11     }
12     int res=0;
13     for(int i=1;i<=n;i++){
14         for(int j=1;j<=n;j++){
15             a[i][j]=c[i][j];
16             if(a[i][j]==b[i][j]) res++;
17         }
18     }
19     return res;
20 }
21 int main(){
22     while(~scanf("%d",&n),n){
23         for(int i=1;i<=n;i++){
24             for(int j=1;j<=n;j++){
25                 scanf("%d",&a[i][j]);
26             }
27         }
28         for(int i=1;i<=n;i++){
29             for(int j=1;j<=n;j++){
30                 scanf("%d",&b[i][j]);
31             }
32         }
33         int ans=0;
34         for(int i=0;i<4;i++){
35             ans=max(ans,solve());
36         }
37         printf("%d\n",ans);
38     }
39     return 0;
40 }
View Code

 

 

end

posted on 2014-08-27 22:26  gaolzzxin  阅读(322)  评论(0编辑  收藏  举报