noip2015 斗地主
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int t, n, ans;
int cnt[20];
void dfs ( int s, int k ) {
if ( k > ans ) return ; //最优性剪枝
if ( s == 0 ) {
if ( k < ans ) ans = k;
return ;
}
int sum = 0;
for ( int i = 2; i <= 14; i ++ )
if ( cnt[i] ) sum ++;
if ( cnt[0] ) sum ++;
ans = min ( ans, k+sum );
for ( int i = 3; i <= 10; i ++ ) { //搜索顺序的改变:优先扩张顺子(情况少)
if ( cnt[i] ) {
bool flag = 1;
for ( int j = i+1; j <= i+4; j ++ )
if ( !cnt[j] ) { flag = 0; break; }
if ( !flag ) continue;
for ( int j = i+4; j <= 14 && cnt[j]; j ++ ) {
for ( int p = i; p <= j; p ++ ) cnt[p] --;
dfs ( s-(j-i+1), k+1 );
for ( int p = i; p <= j; p ++ ) cnt[p] ++;
}
}
}
for ( int i = 3; i <= 12; i ++ ) {
if ( cnt[i] >= 2 ) {
bool flag = 1;
for ( int j = i+1; j <= i+2; j ++ )
if ( cnt[j] < 2 ) { flag = 0; break; }
if ( !flag ) continue;
for ( int j = i+2; j <= 14 && cnt[j] >= 2; j ++ ) {
for ( int p = i; p <= j; p ++ ) cnt[p] -= 2;
dfs ( s-2*(j-i+1), k+1 );
for ( int p = i; p <= j; p ++ ) cnt[p] += 2;
}
}
}
for ( int i = 3; i <= 13; i ++ ) {
if ( cnt[i] >= 3 && cnt[i+1] >= 3 ) {
for ( int j = i+1; j <= 14 && cnt[j] >= 3; j ++ ) {
for ( int p = i; p <= j; p ++ ) cnt[p] -= 3;
dfs ( s-3*(j-i+1), k+1 );
for ( int p = i; p <= j; p ++ ) cnt[p] += 3;
}
}
}
for ( int i = 2; i <= 14; i ++ ) {
if ( cnt[i] >= 3 ) {
cnt[i] -= 3;
for ( int j = 0; j <= 14; j ++ ) {
if ( cnt[j] ) {
cnt[j] --;
dfs ( s-4, k+1 );
cnt[j] ++;
}
if ( cnt[j] >= 2 ) {
cnt[j] -= 2;
dfs ( s-5, k+1 );
cnt[j] += 2;
}
}
dfs ( s-3, k+1 );
cnt[i] += 3;
}
}
for ( int i = 2; i <= 14; i ++ ) {
if ( cnt[i] >= 4 ) {
cnt[i] -= 4;
for ( int j = 0; j <= 14; j ++ ) {
if ( cnt[j] ) {
cnt[j] --;
for ( int p = j+1; p <= 14; p ++ ) {
if ( cnt[p] ) {
cnt[p] --;
dfs ( s-6, k+1 );
cnt[p] ++;
}
}
cnt[j] ++;
}
if ( cnt[j] >= 2 ) {
cnt[j] -= 2;
for ( int p = j+1; p <= 14; p ++ ) {
if ( cnt[p] >= 2 ) {
cnt[p] -= 2;
dfs ( s-8, k+1 );
cnt[p] += 2;
}
}
cnt[j] += 2;
}
}
dfs ( s-4, k+1 );
cnt[i] += 4;
}
}
}
int main ( ) {
freopen ( "landlords.in", "r", stdin );
freopen ( "landlords.out", "w", stdout );
scanf ( "%d%d", &t, &n );
for ( int tt = 1; tt <= t; tt ++ ) {
memset ( cnt, 0, sizeof ( cnt ) );
ans = 0x3f3f3f3f;
for ( int i = 1; i <= n; i ++ ) {
int x, y;
scanf ( "%d%d", &x, &y );
if ( x == 1 ) x += 13;
cnt[x]++;
}
dfs ( n, 0 );
printf ( "%d\n", ans );
}
return 0;
}
双向广搜
普通bfs的修改:
poj1915 模板练习
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int zl[10][10] = {{0,0},{-1,-2},{-1,2},{-2,-1},{-2,1},{2,-1},{2,1},{1,2},{1,-2}};
int n, sx, sy, tx, ty;
struct node {
int x, y;
node ( int x, int y ) : x ( x ), y ( y ) { }
};
queue < node > q;
int flag[505][505], dis[505][505];
int BFS ( ) {
memset ( flag, 0, sizeof ( flag ) );
memset ( dis, 0, sizeof ( dis ) );
while ( !q.empty ( ) ) q.pop ( );
q.push ( node ( sx, sy ) ); q.push ( node ( tx, ty ) ); //起点终点同时入队一起走
flag[sx][sy] = 1; flag[tx][ty] = 2; //起点标记与终点不同
while ( !q.empty ( ) ) {
node a = q.front ( ); q.pop ( );
int x = a.x, y = a.y;
for ( int i = 1; i <= 8; i ++ ) {
int xx = x + zl[i][0], yy = y + zl[i][1];
if ( xx > n || yy > n || xx <= 0 || yy <= 0 ) continue;
if ( flag[x][y] != flag[xx][yy] && flag[x][y] && flag[xx][yy] ) //走到一样的子状态
return dis[x][y] + dis[xx][yy] + 1;
if ( !flag[xx][yy] ) {
q.push ( node ( xx, yy ) );
dis[xx][yy] = dis[x][y] + 1;
flag[xx][yy] = flag[x][y];
}
}
}
return 0;
}
int main ( ) {
int T;
scanf ( "%d", &T );
while ( T -- ) {
scanf ( "%d", &n );
scanf ( "%d%d%d%d", &sx, &sy, &tx, &ty );
sx ++; sy ++; tx ++; ty ++;
int ans = BFS ( );
printf ( "%d\n", ans );
}
return 0;
}
练习:hdu3085(几乎裸)
poj3523
恶心题 不知道哪错了aaaa!!
8.12更新:)
无fuck说:):):)见代码
//A* 双广
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define QWQ short int
using namespace std;
const int zl[5][2] = {{0,0},{0,1},{0,-1},{-1,0},{1,0}};
QWQ sax, say, sbx, sby, scx, scy, tax, tay, tbx, tby, tcx, tcy;
QWQ opt[5];
int H, W, n;
QWQ G[21][21], dis[3][17][17];
QWQ f[17][17][17][17][17][17];
char map[21][21];
struct prenode {
QWQ x, y;
prenode ( QWQ x, QWQ y ) : x (x), y (y) { }
};
bool check ( int x, int y ) {
if ( x <= 0 || y <= 0 || x > H || y > W || map[x][y] == '#' ) return 1;
return 0;
}
void pre_count ( int opp ) {
queue < prenode > q;
QWQ sx, sy;
char des = 'A' + opp;
if ( des == 'A' ) sx = tax, sy = tay;
if ( des == 'B' ) sx = tbx, sy = tby;
if ( des == 'C' ) sx = tcx, sy = tcy;
dis[opp][sx][sy] = 0;
q.push ( prenode ( sx, sy ) );
while ( !q.empty ( ) ) {
prenode u = q.front ( ); q.pop ( );
QWQ x = u.x, y = u.y;
for ( int i = 1; i <= 4; i ++ ) {
QWQ xx = x + zl[i][0], yy = y + zl[i][1];
if ( check ( xx, yy ) ) continue;
if ( dis[opp][xx][yy] > dis[opp][x][y] + 1 ) {
dis[opp][xx][yy] = dis[opp][x][y] + 1;
q.push ( prenode ( xx, yy ) );
}
}
}
}
void init ( ) {
sax = say = sbx = sby = scx = scy = tax = tay = tbx = tby = tcx = tcy = 0;
memset ( opt, 0, sizeof ( opt ) );
memset ( dis, 4, sizeof ( dis ) );
memset ( map, 0, sizeof ( map ) );
memset ( f, 4, sizeof ( f ) );
gets ( map[0] );
for ( int i = 0; i < H; i ++ )
gets ( map[i] );
for ( int i = 0; i < H; i ++ ) {
for ( int j = 1; j < W; j ++ ) {
if ( map[i][j] == 'a' ) sax = i, say = j;
else if ( map[i][j] == 'b' ) sbx = i, sby = j;
else if ( map[i][j] == 'c' ) scx = i, scy = j;
else if ( map[i][j] == 'A' ) tax = i, tay = j, opt[0] = 1;
else if ( map[i][j] == 'B' ) tbx = i, tby = j, opt[1] = 1;
else if ( map[i][j] == 'C' ) tcx = i, tcy = j, opt[2] = 1;
}
}
}
QWQ predict_h ( QWQ ax, QWQ ay, QWQ bx, QWQ by, QWQ cx, QWQ cy ) {
return max ( dis[0][ax][ay], max ( dis[1][bx][by], dis[2][cx][cy] ) );
}
struct node {
QWQ ax, ay, bx, by, cx, cy, g, h; //g为距起点最短路 h为到终点的估值
node ( QWQ ax, QWQ ay, QWQ bx, QWQ by, QWQ cx, QWQ cy, QWQ g, QWQ h ):
ax (ax), ay (ay), bx (bx), by (by), cx (cx), cy (cy), g (g), h (h) {}
bool operator < ( const node & a ) const {
return g + h > a.g + a.h;
}
};
void A_star ( ) {
priority_queue < node > que;
que.push ( node ( sax, say, sbx, sby, scx, scy, 0, predict_h ( sax, say, sbx, sby, scx, scy ) ) );
f[sax][say][sbx][sby][scx][scy] = predict_h ( sax, say, sbx, sby, scx, scy );
QWQ ax = 0, ay = 0, bx = 0, by = 0, cx = 0, cy = 0;
while ( !que.empty ( ) ) {
ax = ay = bx = by = cx = cy = 0;
node cur = que.top ( ); que.pop ( );
if ( cur.g + cur.h > f[cur.ax][cur.ay][cur.bx][cur.by][cur.cx][cur.cy] ) continue;
if ( cur.ax == tax && cur.ay == tay && cur.bx == tbx && cur.by == tby && cur.cx == tcx && cur.cy == tcy ) {
printf ( "%d\n", cur.g );
return ;
}
for ( int i = 0; i <= 4; i ++ ) {
if ( opt[0] ) {
ax = cur.ax + zl[i][0]; ay = cur.ay + zl[i][1];
if ( check ( ax, ay ) ) continue;
}
for ( int j = 0; j <= 4; j ++ ) {
if ( opt[1] ) {
bx = cur.bx + zl[j][0]; by = cur.by + zl[j][1];
if ( check ( bx, by ) ) continue;
if ( bx == ax && by == ay ) continue;
if ( ax == cur.bx && bx == cur.ax && ay == by ) continue;
if ( ay == cur.by && by == cur.ay && ax == bx ) continue;
}
for ( int k = 0; k <= 4; k ++ ) {
if ( opt[2] ) {
cx = cur.cx + zl[k][0]; cy = cur.cy + zl[k][1];
if ( check ( cx, cy ) ) continue;
if ( (cx == ax && cy == ay) || (cx == bx && cy == by) ) continue;
if ( cx == cur.bx && bx == cur.cx && cy == by ) continue;
if ( cx == cur.ax && ax == cur.cx && cy == ay ) continue;
if ( cy == cur.by && by == cur.cy && cx == bx ) continue;
if ( cy == cur.ay && ay == cur.cy && cx == ax ) continue;
}
QWQ pre_h = predict_h ( ax, ay, bx, by, cx, cy );
if ( cur.g + 1 + pre_h < f[ax][ay][bx][by][cx][cy] ) {
f[ax][ay][bx][by][cx][cy] = cur.g + 1 + pre_h;
que.push ( node ( ax, ay, bx, by, cx, cy, cur.g+1, pre_h ) );
}
}
}
}
}
return ;
}
int main ( ) {
while ( scanf ( "%d%d%d", &W, &H, &n ) != EOF && W && H && n ) {
init ( );
for ( QWQ i = 0; i < 3; i ++ )
if ( opt[i] ) pre_count ( i );
else memset ( dis[i], 0, sizeof ( dis[i] ) );//错了两个月是因为括号里dis没写[i]你敢信??
A_star ( );
}
return 0;
}
迭代加深搜索(IDFS)
经典题:埃及分数 (IDA*)
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
ll mu[10005], ans[10005], maxd;
bool check ( ll dep ) {
for ( ll d = dep; d >= 0; d -- )
if ( mu[d] != ans[d] ) return ans[d] == -1 || mu[d] < ans[d];
return 0;
}
ll gcd ( ll a, ll b ) {
return b == 0 ? a : gcd ( b, a % b );
}
bool dfs ( ll dep, ll nex_mu, ll a, ll b ) {
bool flag;
if ( dep == maxd ) {
if ( b % a ) return 0;
mu[dep] = b / a;
if ( check ( dep ) ) memcpy ( ans, mu, sizeof (ll) * ( dep+1 ) );
return true;
}
flag = 0;
nex_mu = max ( nex_mu, b/a+1 ); // 满足a/b的最小分母为b/a+1
for ( int i = nex_mu; ; i ++ ) {
if ( (maxd-dep+1) * b <= i * a ) break; // if ( (maxd-dep+1)/i <= a/b ) break;//A*关键部分
mu[dep] = i;
ll b2 = b * i;
ll a2 = a * i - b;
ll qwq = gcd ( a2, b2 );
if ( dfs ( dep+1, i+1, a2/qwq, b2/qwq ) ) flag = true;
}
return flag;
}
int main ( ) {
int a, b;
scanf ( "%d%d", &a, &b );
bool fl = 0;
for ( maxd = 1; ; maxd ++ ) {//枚举深度上界
memset ( ans, -1, sizeof ( ans ) );
if ( dfs ( 0, b/a+1, a, b ) ) {
fl = 1; break;
}
}
if ( fl ) {
for ( int i = 0; i < maxd; i ++ )
printf ( "1/%lld+", ans[i] );
printf ( "1/%lld\n", ans[maxd] );
} else {
printf ( "no answer!\n" );
}
}
poj2286 The Rotation Game
依旧不知道哪里错了aaaaaaaaaaaaaaaaaaaaaaa
8.13更新!!!结果是审题问题!!不管用不用移动最后都要输出line[matrix[0]]!!(为什么搜索题总是main函数里面错aaaa!!
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int line[30], maxd;
char mu[1005];
int lines[10][10]={ // A(0) <-> F(5) B(1) <-> E(4) C(2) <-> H(7) D(3) <-> G(6)
{ 0, 2, 6,11,15,20,22},// A
{ 1, 3, 8,12,17,21,23},// B
{10, 9, 8, 7, 6, 5, 4},// C
{19,18,17,16,15,14,13},// D
{23,21,17,12, 8, 3, 1},//E
{22,20,15,11, 6, 2, 0},//F
{13,14,15,16,17,18,19},//G
{4, 5, 6, 7, 8, 9, 10},//H
};
int matrix[10] = { 6, 7, 8, 11, 12, 15, 16, 17 };
int predict ( ) {
int maxx = 0x3f3f3f3f;
for ( int i = 1; i <= 3; i ++ ) {
int res = 0;
for ( int j = 0; j < 8; j ++ )
if ( line[matrix[j]] != i ) res ++;
maxx = min ( res, maxx );
}
return maxx;
}
bool check ( ) {
for ( int i = 0; i < 8; i ++ )
if ( line[matrix[i]] != line[matrix[0]] ) return 0;
return 1;
}
void rot ( int i ) {
int yr = line[lines[i][0]];
for ( int j = 0; j < 6; j ++ )
line[lines[i][j]] = line[lines[i][j+1]];
line[lines[i][6]] = yr;
}
bool IDFS ( int dep ) {
if ( dep == maxd ) return check ( );
if ( dep + predict ( ) > maxd ) return 0;
for ( int i = 0; i < 8; i ++ ) {
mu[dep] = i + 'A';
rot ( i );
if ( IDFS ( dep+1 ) ) return 1;
if ( i % 2 == 0 ) rot ( ( i + 5 ) % 8 );
else rot ( ( i + 3 ) % 8 );
}
return 0;
}
int main ( ) {
while ( scanf ( "%d", &line[0] ) != EOF && line[0] != 0 ) {
for ( int i = 1; i < 24; i ++ )
scanf ( "%d", &line[i] );
if ( check ( ) ) {
printf ( "No moves needed\n" );
}
else {
for ( maxd = 1; ; maxd ++ ) {
if ( IDFS ( 0 ) ) break;
}
mu[maxd] = '\0';
printf ( "%s\n", mu );
}
printf ( "%d\n", line[matrix[0]] );
}
return 0;
}
A*算法
k短路
//k短路 A*算法 无向图
//f = h + g h为距起点的估值 g为距终点的最小值
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#define oo 0x3f3f3f3f
using namespace std;
struct matrix { //邻接矩阵存图
int v, w;
matrix ( int v, int w ) : v ( v ), w ( w ) { }
};
vector < matrix > G[N];
void add ( int u, int v, int s ) {
G[u].push ( matrix ( v, s ) );
G[v].push ( matrix ( u, s ) );
}
queue < int > q;
int g[N], vis[N];
void spfa ( ) { //反向跑spfa处理出g
memset ( g, 0x3f3f3f3f, sizeof ( g ) );
q.push ( t );
vis[t] = 1; g[t] = 0;
while ( !q.empty ( ) ) {
int u = q.front ( ); q.pop ( ); vis[u] = 0;
for ( int i = 0; i < G[u].size ( ); i ++ ) {
int v = G[u][i].v;
if ( g[v] > g[u] + G[u][i].w ) {
g[v] = g[u] + G[u][i].w;
if ( !vis[v] ) {
vis[v] = 1;
q.push ( v );
}
}
}
}
}
struct node {
int u, h;
node ( int u, int h ) : u ( u ), h ( h ) { }
bool operator < ( const node a ) const {
return h + g[u] > a.h + g[a.u];
}
};
priority_queue < node > que;
int A_star ( ) {
if ( g[s] == oo ) return -1;
que.push ( node ( s, 0 ) );
while ( !que.empty ( ) ) {
node a = que.top ( ); que.pop ( );
int u = a.u, h = a.h;
cnt[u] ++;
if ( cnt[t] == K ) return h; //第k次到终点
for ( int i = 0; i < G[u].size ( ); i ++ ) {
int v = G[u][i].v;
que.push ( node ( v, h + G[u][i].w ) ); //每个估值都要存入排序
}
}
}
[SDOI2010]魔法猪学院
然而数据加强了目前T一个点
//k短路 A*算法 有向图
//f = h + g h为距起点的估值 g为距终点的最小值
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
#define RG register
#define oo 0x3f3f3f3f
using namespace std;
const int N = 5005;
int n, m, s, t, ans;
double k;
struct matrix {
int v;
double w;
matrix ( int v, double w ) : v ( v ), w ( w ) { }
};
vector < matrix > G[N];
vector < matrix > G1[N];
void add ( int u, int v, double s ) {
G[u].push_back ( matrix ( v, s ) );
G1[v].push_back ( matrix ( u, s ) );
}
double g[N];
int vis[N];
void spfa ( ) {
for ( RG int i = 1; i < N; i ++ )
g[i] = oo;
queue < int > q;
q.push ( t );
vis[t] = 1; g[t] = 0;
while ( !q.empty ( ) ) {
int u = q.front ( ); q.pop ( ); vis[u] = 0;
for ( RG int i = 0; i < G1[u].size ( ); i ++ ) {
int v = G1[u][i].v;
if ( g[v] > g[u] + G1[u][i].w ) {
g[v] = g[u] + G1[u][i].w;
if ( !vis[v] ) {
vis[v] = 1;
q.push ( v );
}
}
}
}
}
struct node {
int u;
double h;
node ( int u, double h ) : u ( u ), h ( h ) { }
bool operator < ( const node a ) const {
return h + g[u] > a.h + g[a.u];
}
};
priority_queue < node > que;
int cnt[N];
void A_star ( ) {
double all = k / g[s]; //优化每个点最多经过次数
que.push ( node ( s, 0 ) );
while ( !que.empty ( ) ) {
node a = que.top ( ); que.pop ( );
int u = a.u;
double h = a.h;
if ( h > k ) return ;
cnt[u] ++;
if ( cnt[u] > all ) continue;
if ( u == t ) {
k -= h; ans ++; continue;
}
for ( RG int i = 0; i < G[u].size ( ); i ++ ) {
int v = G[u][i].v;
que.push ( node ( v, 1.0 * ( h + G[u][i].w ) ) );
}
}
}
int main ( ) {
scanf ( "%d%d%lf", &n, &m, &k );
s = 1, t = n;
for ( RG int i = 1; i <= m; i ++ ) {
int u, v;
double l;
scanf ( "%d%d%lf", &u, &v, &l );
add ( u, v, l );
}
spfa ( );
A_star ( );
printf ( "%d", ans );
return 0;
}