the first CCPC password 123
A http://acm.hust.edu.cn/vjudge/contest/view.action?cid=97380#problem/A
题意:给两个2*2的矩阵,问是否完全相同,其中一个矩阵可以旋转任意次90度。
解法:转4次都测一下是否相同。
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e2+10; 23 int a[M]; 24 int b[M]; 25 char str[][16]={"POSSIBLE","IMPOSSIBLE"}; 26 bool judge(int d){ 27 for(int i=0;i<4;i++){ 28 if(a[i]!=b[(i+d)%4]) return false; 29 } 30 return true; 31 } 32 int solve(){ 33 for(int i=0;i<4;i++){ 34 if(judge(i)) return 0; 35 } 36 return 1; 37 } 38 int main(){ 39 #ifdef txtout 40 freopen("in.txt","r",stdin); 41 freopen("out.txt","w",stdout); 42 #endif 43 int t; 44 while(~scanf("%d",&t)){ 45 int cas=1; 46 while(t--){ 47 scanf("%d%d%d%d",&a[0],&a[1],&a[3],&a[2]); 48 scanf("%d%d%d%d",&b[0],&b[1],&b[3],&b[2]); 49 printf("Case #%d: %s ",cas++,str[solve()]); 50 } 51 } 52 return 0; 53 }
D http://acm.hust.edu.cn/vjudge/contest/view.action?cid=97380#problem/D
题意:将n个长度为a,价值为v的木棍放在长度为L的桌面上,其中两端的木棍只要保证中心在桌面上就行,问能得到的最大价值。
解法:就是01背包问题,只是其中有两个物体的花费可以除以2.下面用了一种非常不优美,但是比较好理解的dp,卡过。把所有长度*2避免浮点数。然后dp【i】【j】【k】表示前i个物品花费了j的长度有k个是减半的最大价值。i需要滚动。
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e3+10; 23 int a[M]; 24 int v[M]; 25 int n,L; 26 LL dp[2][M<<2][3]; 27 void init(int now){ 28 for(int i=0;i<=L;i++){ 29 for(int j=0;j<3;j++){ 30 dp[now][i][j]=-1; 31 } 32 } 33 } 34 void Copy(int now,int pre){ 35 for(int i=0;i<=L;i++){ 36 for(int j=0;j<3;j++){ 37 dp[now][i][j]=dp[pre][i][j]; 38 } 39 } 40 } 41 void update(int now,int i,int j,LL value){ 42 dp[now][i][j]=max(dp[now][i][j],value); 43 } 44 LL solve(){ 45 L<<=1; 46 for(int i=1;i<=n;i++){ 47 a[i]<<=1; 48 } 49 init(0); 50 dp[0][0][0]=0; 51 int now=0; 52 int pre=1; 53 for(int i=1;i<=n;i++){ 54 now^=1; 55 pre^=1; 56 Copy(now,pre); 57 for(int j=0;j<=L;j++){ 58 for(int k=0;k<3;k++){ 59 LL &ans=dp[pre][j][k]; 60 if(ans==-1) continue; 61 if(j+a[i]<=L){ 62 update(now,j+a[i],k,ans+v[i]); 63 } 64 if(k<2&&j+(a[i]>>1)<=L){ 65 update(now,j+(a[i]>>1),k+1,ans+v[i]); 66 } 67 } 68 } 69 } 70 LL res=0; 71 for(int i=1;i<=n;i++){ 72 res=max(res,0LL+v[i]); 73 } 74 for(int i=0;i<=L;i++){ 75 for(int j=0;j<3;j++){ 76 res=max(res,dp[now][i][j]); 77 } 78 } 79 return res; 80 } 81 int main(){ 82 #ifdef txtout 83 freopen("in.txt","r",stdin); 84 freopen("out.txt","w",stdout); 85 #endif 86 int t; 87 while(~scanf("%d",&t)){ 88 int cas=1; 89 while(t--){ 90 scanf("%d%d",&n,&L); 91 for(int i=1;i<=n;i++){ 92 scanf("%d%d",&a[i],&v[i]); 93 } 94 printf("Case #%d: %lld ",cas++,solve()); 95 } 96 } 97 return 0; 98 }
G http://acm.hust.edu.cn/vjudge/contest/view.action?cid=97380#problem/G
题意:给一盘围棋,XO分别是黑白棋,点是空的,问再放一个X能否杀掉一部分o,能杀就是o的连通块边缘没有空。
解法1:dfs出o的连通块,统计与之相邻的空格有几个,如果只有一个就可以杀。
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e2+10; 23 char a[M][M]; 24 char str[][32]={"Can kill in one move!!!","Can not kill in one move!!!"}; 25 bool vis[M][M]; 26 bool sum[M][M]; 27 int dx[]={0,0,1,-1}; 28 int dy[]={1,-1,0,0}; 29 void init(bool v[M][M]){ 30 for(int i=0;i<9;i++){ 31 for(int j=0;j<9;j++){ 32 v[i][j]=false; 33 } 34 } 35 } 36 bool inside(int x,int y){ 37 return x>=0&&x<9&&y>=0&&y<9; 38 } 39 void dfs(int x,int y){ 40 vis[x][y]=true; 41 for(int i=0;i<4;i++){ 42 int tx=x+dx[i]; 43 int ty=y+dy[i]; 44 if(!inside(tx,ty)) continue; 45 if(vis[tx][ty]) continue; 46 if(a[tx][ty]=='x') continue; 47 if(a[tx][ty]=='.'){ 48 sum[tx][ty]=true; 49 continue; 50 } 51 dfs(tx,ty); 52 } 53 } 54 bool can_kill(int sx,int sy){ 55 init(sum); 56 dfs(sx,sy); 57 int res=0; 58 for(int i=0;i<9;i++){ 59 for(int j=0;j<9;j++){ 60 if(sum[i][j]){ 61 res++; 62 if(res>1) return false; 63 } 64 } 65 } 66 return true; 67 } 68 int solve(){ 69 init(vis); 70 for(int i=0;i<9;i++){ 71 for(int j=0;j<9;j++){ 72 if(vis[i][j]) continue; 73 if(a[i][j]!='o') continue; 74 if(can_kill(i,j)) return 0; 75 } 76 } 77 return 1; 78 } 79 int main(){ 80 #ifdef txtout 81 freopen("in.txt","r",stdin); 82 freopen("out.txt","w",stdout); 83 #endif 84 int t; 85 while(~scanf("%d",&t)){ 86 int cas=1; 87 while(t--){ 88 for(int i=0;i<9;i++){ 89 scanf("%s",a[i]); 90 } 91 printf("Case #%d: %s ",cas++,str[solve()]); 92 } 93 } 94 return 0; 95 }
解法2:bfs出连通块,思路同上。
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e2+10; 23 char a[M][M]; 24 char str[][32]={"Can kill in one move!!!","Can not kill in one move!!!"}; 25 bool vis[M][M]; 26 bool sum[M][M]; 27 int dx[]={0,0,1,-1}; 28 int dy[]={1,-1,0,0}; 29 struct Q{ 30 int x,y; 31 }now,pre; 32 queue<Q> q; 33 void init(bool v[M][M]){ 34 for(int i=0;i<9;i++){ 35 for(int j=0;j<9;j++){ 36 v[i][j]=false; 37 } 38 } 39 } 40 bool inside(int x,int y){ 41 return x>=0&&x<9&&y>=0&&y<9; 42 } 43 void bfs(int x,int y){ 44 vis[x][y]=true; 45 now.x=x; 46 now.y=y; 47 while(!q.empty()) q.pop(); 48 q.push(now); 49 while(!q.empty()){ 50 pre=q.front(); 51 q.pop(); 52 for(int i=0;i<4;i++){ 53 int tx=pre.x+dx[i]; 54 int ty=pre.y+dy[i]; 55 if(!inside(tx,ty)) continue; 56 if(vis[tx][ty]) continue; 57 if(a[tx][ty]=='x') continue; 58 if(a[tx][ty]=='.'){ 59 sum[tx][ty]=true; 60 continue; 61 } 62 vis[tx][ty]=true; 63 now.x=tx; 64 now.y=ty; 65 q.push(now); 66 } 67 } 68 } 69 bool can_kill(int sx,int sy){ 70 init(sum); 71 bfs(sx,sy); 72 int res=0; 73 for(int i=0;i<9;i++){ 74 for(int j=0;j<9;j++){ 75 if(sum[i][j]){ 76 res++; 77 if(res>1) return false; 78 } 79 } 80 } 81 return true; 82 } 83 int solve(){ 84 init(vis); 85 for(int i=0;i<9;i++){ 86 for(int j=0;j<9;j++){ 87 if(vis[i][j]) continue; 88 if(a[i][j]!='o') continue; 89 if(can_kill(i,j)) return 0; 90 } 91 } 92 return 1; 93 } 94 int main(){ 95 #ifdef txtout 96 freopen("in.txt","r",stdin); 97 freopen("out.txt","w",stdout); 98 #endif 99 int t; 100 while(~scanf("%d",&t)){ 101 int cas=1; 102 while(t--){ 103 for(int i=0;i<9;i++){ 104 scanf("%s",a[i]); 105 } 106 printf("Case #%d: %s ",cas++,str[solve()]); 107 } 108 } 109 return 0; 110 }
H http://acm.hust.edu.cn/vjudge/contest/view.action?cid=97380#problem/H
题意:给出4*4的矩阵,数字为1到4,*为未确定,给*赋值1到4,使得每行每列,四个角的2*2内都没有相同元素,保证唯一解。
解法1:把每一个位置可能的情况都存下set,每次出现只剩一个就说明该位置确定,然后将其所在行列块都删去这个数,直至推出答案。
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e2+10; 23 char a[M][M]; 24 int b[M][M]; 25 int dx[]={0,0,1,1}; 26 int dy[]={0,1,0,1}; 27 set<int> s[M][M]; 28 void init(){ 29 for(int i=0;i<4;i++){ 30 for(int j=0;j<4;j++){ 31 s[i][j].clear(); 32 if(a[i][j]=='*'){ 33 for(int k=1;k<=4;k++){ 34 s[i][j].insert(k); 35 } 36 } 37 else{ 38 s[i][j].insert(a[i][j]-'0'); 39 } 40 } 41 } 42 } 43 void Erase(int x,int y,int value){ 44 for(int i=0;i<4;i++){ 45 s[i][y].erase(value); 46 s[x][i].erase(value); 47 } 48 if(x&1) x--; 49 if(y&1) y--; 50 for(int i=0;i<4;i++){ 51 int tx=x+dx[i]; 52 int ty=y+dy[i]; 53 s[tx][ty].erase(value); 54 } 55 } 56 void solve(){ 57 init(); 58 bool flag=true; 59 while(flag){ 60 flag=false; 61 for(int i=0;i<4;i++){ 62 for(int j=0;j<4;j++){ 63 if(s[i][j].size()==1){ 64 flag=true; 65 b[i][j]=*s[i][j].begin(); 66 Erase(i,j,b[i][j]); 67 } 68 } 69 } 70 } 71 } 72 int main(){ 73 #ifdef txtout 74 freopen("in.txt","r",stdin); 75 freopen("out.txt","w",stdout); 76 #endif 77 int t; 78 while(~scanf("%d",&t)){ 79 int cas=1; 80 while(t--){ 81 for(int i=0;i<4;i++){ 82 scanf("%s",a[i]); 83 } 84 solve(); 85 printf("Case #%d: ",cas++); 86 for(int i=0;i<4;i++){ 87 for(int j=0;j<4;j++){ 88 printf("%d",b[i][j]); 89 } 90 puts(""); 91 } 92 } 93 } 94 return 0; 95 }
解法2:dfs每一个位置的取值,暴力所有情况。
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e2+10; 23 char a[M][M]; 24 int b[M][M]; 25 int dx[]={0,0,1,1}; 26 int dy[]={0,1,0,1}; 27 void init(){ 28 for(int i=0;i<4;i++){ 29 for(int j=0;j<4;j++){ 30 b[i][j]=-1; 31 if(a[i][j]!='*'){ 32 b[i][j]=a[i][j]-'0'; 33 } 34 } 35 } 36 } 37 bool same(int x,int y,int value){ 38 for(int i=0;i<4;i++){ 39 if(b[x][i]==value) return true; 40 if(b[i][y]==value) return true; 41 } 42 if(x&1) x--; 43 if(y&1) y--; 44 for(int i=0;i<4;i++){ 45 int tx=x+dx[i]; 46 int ty=y+dy[i]; 47 if(b[tx][ty]==value) return true; 48 } 49 return false; 50 } 51 bool dfs(int x,int y){ 52 if(x==4) return true; 53 if(y==4) return dfs(x+1,0); 54 if(b[x][y]!=-1) return dfs(x,y+1); 55 for(int i=1;i<=4;i++){ 56 if(same(x,y,i)) continue; 57 b[x][y]=i; 58 if(dfs(x,y+1)) return true; 59 b[x][y]=-1; 60 } 61 return false; 62 } 63 void solve(){ 64 init(); 65 dfs(0,0); 66 } 67 int main(){ 68 #ifdef txtout 69 freopen("in.txt","r",stdin); 70 freopen("out.txt","w",stdout); 71 #endif 72 int t; 73 while(~scanf("%d",&t)){ 74 int cas=1; 75 while(t--){ 76 for(int i=0;i<4;i++){ 77 scanf("%s",a[i]); 78 } 79 solve(); 80 printf("Case #%d: ",cas++); 81 for(int i=0;i<4;i++){ 82 for(int j=0;j<4;j++){ 83 printf("%d",b[i][j]); 84 } 85 puts(""); 86 } 87 } 88 } 89 return 0; 90 }
L http://acm.hust.edu.cn/vjudge/contest/view.action?cid=97380#problem/L
题意:给n种字母,问组成最短的回文串的长度。
解法:n*2-1。
1 //#define debug 2 //#define txtout 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<cctype> 8 #include<ctime> 9 #include<iostream> 10 #include<algorithm> 11 #include<vector> 12 #include<queue> 13 #include<stack> 14 #include<map> 15 #include<set> 16 #define mt(a,b) memset(a,b,sizeof(a)) 17 using namespace std; 18 typedef long long LL; 19 const double eps=1e-8; 20 const double pi=acos(-1.0); 21 const int inf=0x3f3f3f3f; 22 const int M=1e5+10; 23 int a[M]; 24 int main(){ 25 #ifdef txtout 26 freopen("in.txt","r",stdin); 27 freopen("out.txt","w",stdout); 28 #endif 29 int t,n; 30 while(~scanf("%d",&t)){ 31 int cas=1; 32 while(t--){ 33 scanf("%d",&n); 34 printf("Case #%d: %d ",cas++,n*2-1); 35 } 36 } 37 return 0; 38 }
end