以下所有代碼均去掉板子
這個是板子
#include<iostream>
#include<queue>
#include<cstring>
#include<string>
#include<sstream>
#include<map>
#include<vector>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<stack>
#include<ctime>
using namespace std;
#define rep(i,aa,bb) for(register int i=aa;i<=bb;i++)
#define rrep(i,aa,bb) for(register int i=aa;i>=bb;i--)
#define mset(var,val) memset(var,val,sizeof(var))
#define LL long long
#define eps 0.000001
#define inf 0x7f7f7f7f
#define llinf 1e18
#define exp 0.000001
#define pai 3.141592654
#define random(x) rand()%(x)
#define lowbit(x) x&(-x)
inline int read()
{
int x=0,y=1;char a=getchar();while ( a>'9' || a<'0'){if ( a=='-')y=-1;a=getchar();}
while ( a>='0' && a<='9' ){ x=(x<<3)+(x<<1)+a-'0'; a=getchar();}return x*y;
}
一、ZOJ 2172 Symmetric Order
題意:
給一些字符串,按照特定順序輸出。
題解:
dfs回溯的順序。或者奇偶順序。
以下是核心代碼(去掉了板子)
#define N 19
int n; char a[N][26];
void dfs(int dep){
if ( dep == n/2 + 1 ){
if ( n & 1 == 1 ){
printf("%s\n",a[n]);
}
return ;
}
printf("%s\n",a[dep*2-1]);
dfs(dep+1);
printf("%s\n",a[dep*2]);
}
int main()
{
srand((int)time(0));
int tot = 0 ;
while ( scanf("%d",&n) != EOF && n ){
printf("SET %d\n",++tot);
rep(i,1,n){
scanf("%s",a[i]);
}
dfs(1);
}
return 0;
}
二、HDU - 1312 Red and Black
題意:
一個人被困在方形迷宮內,起點是@,能走的地方是‘.’也就是黑格,不能走的地方是#也就是紅格。求這個人踩到多少個黑格?
input
6 9
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
11 9
.#.........
.#.#######.
.#.#.....#.
.#.#.###.#.
.#.#..@#.#.
.#.#####.#.
.#.......#.
.#########.
...........
11 6
..#..#..#..
..#..#..#..
..#..#..###
..#..#..#@.
..#..#..#..
..#..#..#..
7 7
..#.#..
..#.#..
###.###
...@...
###.###
..#.#..
..#.#..
0 0
output
45
59
6
13
題解一:
基礎dfs,子問題求解。
int n,m;char ma[50][50];
int dfs(int x,int y){
if ( x < 0 || x >= n ) return 0 ;
if ( y < 0 || y >= m ) return 0 ;
if ( ma[x][y] == '#') return 0 ;
ma[x][y] = '#';
return 1+dfs(x-1,y)+dfs(x+1,y)+dfs(x,y-1)+dfs(x,y+1);
}
int main()
{
while ( scanf("%d%d",&m,&n) != EOF ){
rep(i,0,n-1) scanf("%s",ma[i]);
rep(i,0,n-1) rep(j,0,m-1){
if ( ma[i][j] == '@' ){
printf("%d\n",dfs(i,j));
}
}
}
return 0;
}
題解二:
基礎bfs,多狀態計數。
int n,m;char ma[50][50];
struct node {
int x,y;
node (){ }
};
int nx[4][2]={
1,0,-1,0,0,1,0,-1
};
queue<node>q; int ans = 0 ; bool vis[50][50];
int bfs(int x,int y){
node aaa; aaa.x = x; aaa.y = y; q.push(aaa);
vis[x][y] = 1; ans++;
while ( !q.empty() ) {
node a = q.front(); q.pop() ; node b;
for (int i = 0; i < 4; i++){
b.x = a.x + nx[i][0];
b.y = a.y + nx[i][1];
if ( b.x>=0 && b.x<n && b.y>=0 && b.y<m && !vis[b.x][b.y] && ma[b.x][b.y]!='#' ){
vis[ b.x ][ b.y ] = 1;
ans++;
q.push(b);
}
}
}
return ans;
}
int main()
{
while ( scanf("%d%d",&m,&n) != EOF ){
while ( !q.empty() ) q.pop();
ans = 0 ; mset(vis,0); mset(ma,0);
rep(i,0,n-1) scanf("%s",ma[i]);
rep(i,0,n-1) rep(j,0,m-1){
if ( ma[i][j] == '@' ){
printf("%d\n",bfs(i,j));
break;
}
}
}
return 0;
}
三、luogu P1120 小木棍(POJ 1011 Sticks)
題意:
喬治有一些同樣長的小木棍,他把這些木棍隨意砍成幾段,直到每段的長都不超過50。
現在,他想把小木棍拼接成原來的樣子,但是卻忘記了自己開始時有多少根木棍和它們的長度。
給出每段小木棍的長度,編程幫他找出原始木棍的最小可能長度。
input
9
5 2 1 5 2 1 5 2 1
output
6
題解:
雙階段dfs,加極限剪枝。
sort(a+1,a+n+1,cmp);
剪枝一:
排序。 木棍由大到小排序。理由:長度小,而且數量多的木棍,相比於同樣總長的,長度大,數量少的木棍,更加靈活。例如:5和4能組成9。5,2,1和1也能組成9,但是如果當前在組第3組木棍,還有兩組木棍要組合,那麼我肯定優先選擇5和4,這樣,才能把更多可能性給第4組和第5組,第4組和第5組才更有可能組成長度爲規定的長木棍。
while ( a[i] == a[i+1] )
i++;
剪枝二:
去重。a[i] 有相同值時候,我們只dfs第一個值(在dep層dfs),下一個階段(在dep+1層)我們會dfs,a[i+1],(在dep+2層)dfs,a[i+2]。如果在dep層dfs,a[i+1],那麼會多次枚舉,走相同的dfs。每一層都多走,相當浪費時間資源。
if ( len == a[i] || len == pp )
return 0 ;
剪枝三:
當我們枚舉的這根長木棍剩餘值,正好等於,當前枚舉的a[i]時,我們用a[i]填補枚舉的這根長木棍,如果,a[i]以後的短木棍都無法拼湊成剩下的長木棍,那麼我們用比a[i]更小的短木棍更不可能拼湊成剩下的長木棍。栗子:len5,pp6,a[i] == 5 ,剩下的短木棍爲4,4,3。代入驗證即可。
剪枝四:
當前a[i]放到,當前枚舉的長木棍中(當前長木棍未放入任何值)之後,都無法拼接剩下的長木棍,那麼,pp這個值肯定是無法使用的。
if ( len < a[cnt] ) return 0 ;
剪枝五:
現在需要的短木棍長度,比最短的那個短木棍還小。那麼pp的值不合適。
bool cmp(int x,int y)
{
return x>y;
}
int n,t,sum=0,cnt=0,a[70],res,vis[70],pp;
int dfs(int len,int sta,int now){
if ( now == res ){
return 1;
}
if ( len == 0 )
if ( dfs(pp,1,now+1) )
return 1;
if ( len < a[cnt] ) return 0 ;
for (int i = sta; i <= cnt ; i++){
if ( !vis[i] && a[i] <= len ){
vis[i] = 1;
if ( dfs(len-a[i],i+1,now) )
return 1;
vis[i] = 0;
if ( len == a[i] || len == pp )
return 0 ;
while ( a[i] == a[i+1] )
i++;
}
}
return 0 ;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&t);
if(t<=50)
{
sum+=t;
a[++cnt]=t;
}
}
sort(a+1,a+n+1,cmp);
for(int i=a[1];i<=sum/2;i++)
if(sum%i==0)
{
pp=i; // 全局記錄長度
res=sum/i;
if(dfs(i,1,0))
{
printf("%d",i);
return 0;
}
}
printf("%d",sum);
return 0;
}