【日更】蓝书第一章

打完这个赛季(上个青),刷刷蓝书

题目合集:

https://cn.vjudge.net/article/737

eg1:

https://cn.vjudge.net/problem/UVA-11292

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<ctime>
#include<string>
#include<vector>
using namespace std;
typedef long long ll;
const int MAXN = 2e4 + 5;
const int maxn = MAXN;
const long long MOD = 1e8 + 7;
#define rep(i,t,n)  for(int i =(t);i<=(n);++i)
#define per(i,n,t)  for(int i =(n);i>=(t);--i)
#define mmm(a,b) memset(a,b,sizeof(a))
int phi[MAXN], prime[MAXN];

int isntp[maxn];
void sieve(int n) {
    int m = (int)sqrt(n + 0.5);
    mmm(isntp, 0);
    rep(i, 2, m)if (!isntp[i])for (int j = i * i; j <= n; j += i)isntp[j] = 1;

}
int ans[maxn];

int smain();
#define ONLINE_JUDGE
int main() {

    //ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    FILE *myfile;
    myfile = freopen("C:\Users\acm-14\Desktop\test\b.in", "r", stdin);
    if (myfile == NULL)
        fprintf(stdout, "error on input freopen
");
    FILE *outfile;
    outfile = freopen("C:\Users\acm-14\Desktop\test\out.txt", "w", stdout);
    if (outfile == NULL)
        fprintf(stdout, "error on output freopen
");
    long _begin_time = clock();
#endif
    smain();
#ifndef ONLINE_JUDGE
    long _end_time = clock();
    printf("time = %ld ms.", _end_time - _begin_time);
#endif
    return 0;
}
int head[maxn];
int cost[maxn];

int smain()
{
    int n, m;
    while (cin >> n >> m&&n) {
        rep(i, 1, n)cin >> head[i];
        rep(i, 1, m)cin >> cost[i];
        sort(head + 1, head + 1 + n);
        sort(cost + 1, cost + 1 + m);
        int p = 1;
        long long ans = 0;
        int f = 1;
        rep(i, 1, n) {
            if (p > m) {
                f = 0; break;
            }
            while (head[i] > cost[p])p++;
            ans += cost[p],p++;
            
        }
        if (!f)puts("Loowater is doomed!");
        else cout << ans << endl;
    }
    

    /*don't delete*/
    return 0;
}
/*,
2 3
5
4
7
8
4
2 1
5
5
10
0 0
*/
View Code

算法:无脑贪心+排序

坑:本来想少写一个flag,结果想错了。。

ps:静电容键盘到了,敲敲水题试一下。打字只要轻轻压(摸)一下就行,以至于手指经过别的键总是会碰到,也很容易打两次同一个字母,感觉习惯了的话代码速度可以上天。

eg2

https://cn.vjudge.net/problem/UVA-11729

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<ctime>
#include<string>
#include<vector>
using namespace std;
typedef long long ll;
const int MAXN = 1e3 + 5;
const int maxn = MAXN;
const long long MOD = 1e8 + 7;
#define rep(i,t,n)  for(int i =(t);i<=(n);++i)
#define per(i,n,t)  for(int i =(n);i>=(t);--i)
#define mmm(a,b) memset(a,b,sizeof(a))
#define x first
#define y second
int phi[MAXN], prime[MAXN];

int isntp[maxn];
void sieve(int n) {
    int m = (int)sqrt(n + 0.5);
    mmm(isntp, 0);
    rep(i, 2, m)if (!isntp[i])for (int j = i * i; j <= n; j += i)isntp[j] = 1;

}
int ans[maxn];

int smain();
#define ONLINE_JUDGE
int main() {

    //ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    FILE *myfile;
    myfile = freopen("C:\Users\acm-14\Desktop\test\b.in", "r", stdin);
    if (myfile == NULL)
        fprintf(stdout, "error on input freopen
");
    FILE *outfile;
    outfile = freopen("C:\Users\acm-14\Desktop\test\out.txt", "w", stdout);
    if (outfile == NULL)
        fprintf(stdout, "error on output freopen
");
    long _begin_time = clock();
#endif
    smain();
#ifndef ONLINE_JUDGE
    long _end_time = clock();
    printf("time = %ld ms.", _end_time - _begin_time);
#endif
    return 0;
}
int b[maxn], j[maxn];
pair<int, int> p[maxn];
int smain()
{
    int n;
    int kase = 0;
    while (cin >> n && n) {
        printf("Case %d: ", ++kase);
        rep(i, 1, n) {
            cin >> p[i].y >> p[i].x;
        }
        sort(p + 1, p + 1 + n);
        int cur = 0;;
        int ans = 0;
        per(i,n,1) {
            cur += p[i].y;
            ans = max(ans, cur + p[i].x);
        }
        cout << ans << endl;
    }

    /*don't delete*/
    return 0;
}
/*,
3
2 5
3 2
2 1
3
3 3
4 4
5 5

0 0
*/
View Code

算法:直觉贪心+排序

ps:贪心的依据:ans=max(ans,cur+army[i].job)答案有这样的形式,cur是当前交待的总时间,考虑相邻的两个,总的cur是一样的,显然army.job短的人放在后面更优,所以就按照job降序排序了。

电容键盘可以光速连按啊prprprprprprprprprrprprprprpprprprprprprprrprprrprprprprrprpprrpprprpr

eg3‘

https://cn.vjudge.net/problem/UVA-11300

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<ctime>
#include<string>
#include<vector>
using namespace std;
typedef long long ll;
const int MAXN = 1e6 + 5;
const int maxn = MAXN;
const long long MOD = 1e9 + 7;
#define rep(i,t,n)  for(int i =(t);i<=(n);++i)
#define per(i,n,t)  for(int i =(n);i>=(t);--i)
#define mmm(a,b) memset(a,b,sizeof(a))
#define x first
#define y second

int smain();
#define ONLINE_JUDGE
int main() {

    //ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    FILE *myfile;
    myfile = freopen("C:\Users\acm-14\Desktop\test\b.in", "r", stdin);
    if (myfile == NULL)
        fprintf(stdout, "error on input freopen
");
    FILE *outfile;
    outfile = freopen("C:\Users\acm-14\Desktop\test\out.txt", "w", stdout);
    if (outfile == NULL)
        fprintf(stdout, "error on output freopen
");
    long _begin_time = clock();
#endif
    smain();
#ifndef ONLINE_JUDGE
    long _end_time = clock();
    printf("time = %ld ms.", _end_time - _begin_time);
#endif
    return 0;
}
long long A[maxn], C[maxn], tot, M;

int smain()
{
    int n;
    while (cin >> n) {
         tot = 0;
         rep(i, 1, n)scanf("%lld", &A[i]), tot += A[i];
         M = tot / n;
         C[0] = 0;
         rep(i, 1, n)C[i] = C[i - 1] + A[i] - M;
         sort(C, C + n);
         long long x1 = C[n / 2], ans = 0;
         for (int i = 0; i < n; i++) {
             ans += abs(x1 - C[i]);
         }
         printf("%lld
", ans);
    }

    /*don't delete*/
    return 0;
}
/*,
3
100
100
100
4
1
2
5
4

*/
View Code

算法:代数分析题 。中位数求方程组目标函数最值 

ps:第一道代数题,,用一个for递推地算出系数,把系数存在数组c里,想不到想不到,

eg4:

https://cn.vjudge.net/problem/UVALive-3708

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<ctime>
#include<string>
#include<vector>
using namespace std;
typedef long long ll;
const int MAXN = 1e6 + 5;
const int maxn = MAXN;
const long long MOD = 1e9 + 7;
#define rep(i,t,n)  for(int i =(t);i<=(n);++i)
#define per(i,n,t)  for(int i =(n);i>=(t);--i)
#define mmm(a,b) memset(a,b,sizeof(a))
#define x first
#define y second

int smain();
#define ONLINE_JUDGE
int main() {

    //ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    FILE *myfile;
    myfile = freopen("C:\Users\acm-14\Desktop\test\b.in", "r", stdin);
    if (myfile == NULL)
        fprintf(stdout, "error on input freopen
");
    FILE *outfile;
    outfile = freopen("C:\Users\acm-14\Desktop\test\out.txt", "w", stdout);
    if (outfile == NULL)
        fprintf(stdout, "error on output freopen
");
    long _begin_time = clock();
#endif
    smain();
#ifndef ONLINE_JUDGE
    long _end_time = clock();
    printf("time = %ld ms.", _end_time - _begin_time);
#endif
    return 0;
}


int smain()
{
    int n, m;
    while (cin >> n >> m) {
        double ans = 0;
        rep(i, 1, n - 1) {
            double pos = (double)(n + m) / n * i;
            ans += abs(pos - floor(pos + 0.5))/(n+m);
        }
        printf("%.4lf
", ans * 10000);
    }
    /*don't delete*/
    return 0;
}
/*,
3
100
100
100
4
1
2
5
4

*/
View Code

算法:几何想法 

ps:四舍五入找最近点是真的sao

eg5

https://cn.vjudge.net/problem/UVA-10881

算法:完全弹性碰撞的想法题(两个完全弹性碰撞的粒子可以看成互相穿过去!)+rank记录顺序技巧

坑:sample output复制到vs里面被过滤掉了回车,然后输出格式错了orz。另外turning细节,前后两个一起赋值。

#include <iostream>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include<cstdio>
#include<vector>
#include<ctime>
#include<string>
#include<map>
#define rep(i,t,n)  for(int i =(t);i<=(n);++i)
#define per(i,n,t)  for(int i =(n);i>=(t);--i)
#define mmm(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn = 1e4 + 5;
const double PI = acos(-1.0);
struct ant {
    int x, rk;
    int dir;
}a[maxn],b[maxn];
bool cmp(ant a, ant b) { return a.x < b.x; }
bool cmp2(ant a, ant b) { return a.rk < b.rk; }
int main()
{
    int kase = 0;
    int t; cin >> t; while (t--) {
        int l, time, n;
        cin >> l >> time >> n;
        rep(i, 1, n) {
            string S; int x;
            cin >> x >> S;
            a[i].x = x; a[i].dir = S == "R" ? 1 : -1;
            a[i].rk = i;
        }
        sort(a + 1, a + 1 + n,cmp);
        rep(i, 1, n) {
            b[i].x = a[i].x + a[i].dir * time;
            b[i].dir = a[i].dir;
            
        }
        sort(b + 1, b + 1 + n,cmp);

        rep(i, 1, n)b[i].rk = a[i].rk;
        rep(i, 1, n - 1)if (b[i].x == b[i + 1].x)b[i].dir =b[i+1].dir= 0;
        sort(b + 1, b + 1 + n, cmp2);
        printf("Case #%d:
", ++kase);
        rep(i, 1, n) {
            if (b[i].x<0 || b[i].x>l)puts("Fell off");
            else {
                cout << b[i].x << ' ';
                if (b[i].dir == 0)puts("Turning");
                else puts(b[i].dir == 1 ? "R" : "L");
            }
        }
        cout << endl;
    }
    //cin >> t;
}
/*
Sample Input
2
10 1 4
1 R
5 R
3 L
10 R
10 2 3
4 R
5 L
8 R


Sample Output
Case #1:
2 Turning
6 R
2 Turning
Fell off
Case #2:
3 L
6 R
10 R*/
View Code

 eg6

算法:贪心地做,蓝书上有证明,不怎么看得懂

坑:i写成j,WF到底是WF

#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second

typedef double  db;
typedef long long ll;
const int MAXN = 12;;
const int maxn = MAXN;
const double eps = 1e-8;
const double PI = acos(-1.0);


string view[maxn][maxn];
int pos[maxn][maxn][maxn];
int n;
void get(int k, int i, int j, int len, int &x, int &y, int &z) {
    int nn = n - 1;
    if (k == 0) { x = len, z = i, y = j; }
    if (k == 1) { y = len, x = nn - j; z = i; }
    if (k == 2) { z = i, x = nn - len, y = nn - j; }
    if (k == 3) { z = i; x = j; y = nn - len; }
    if (k == 4) { x = nn - i, y = j, z = len; }
    if (k == 5) { y = j, x =  i, z = nn - len; }
}

int main() {
    
    while (cin >> n && n) {
        rep(i, 0, n - 1)rep(k, 0, 5) {
            cin >> view[k][i];
        }
        int nn = n - 1;
        rep(i, 0, nn)rep(j, 0, nn)rep(k, 0, nn)pos[i][j][k] = '#';
        int x = 0, y = 0, z = 0;
        rep(k, 0, 5)rep(i, 0,  nn)rep(j, 0, nn) {
            if (view[k][i][j] == '.') {
                rep(d, 0, nn) {
                    get(k, i, j, d, x, y, z);
                    pos[x][y][z] = '.';
                }
            }
        }
        while (1) {
            bool done = 1;
            
            rep(k, 0, 5)rep(i, 0, nn)rep(j, 0, nn)if (view[k][i][j] != 0) {
                int bug = 1;
                rep(d, 0, nn) {
                    get(k, i, j, d, x, y, z);
                    if (pos[x][y][z] == '.')continue;
                    if (pos[x][y][z] == '#') {
                        pos[x][y][z] = view[k][i][j];
                        {bug = 0; break; }
                    }
                    if (pos[x][y][z] == view[k][i][j]) {
                        bug = 0; break;
                    }
                    pos[x][y][z] = '.';
                    done = 0;
                }
                if (0) {
                    rep(i, 0, nn) { rep(j, 0, nn) { rep(k, 0, nn)cout << (char)pos[j][k][i]; cout << endl; }cout << endl; }
                    rep(i, 0, nn)cout << "---"; cout << endl;
                }
            }
            if (done)break;
        }
        
        int ans = 0;
        rep(i, 0, nn)rep(j, 0, nn)rep(k, 0, nn)if (pos[i][j][k]!='.')ans++;
        //cout << ans << endl;
        printf("Maximum weight: %d gram(s)
", ans);
    }
}
/*
3
.R. YYR .Y. RYY .Y. .R.
GRB YGR BYG RBY GYB GRB
.R. YRR .Y. RRY .R. .Y.


2
ZZ ZZ ZZ ZZ ZZ ZZ
ZZ ZZ ZZ ZZ ZZ ZZ
0



*/
View Code

 eg7

https://cn.vjudge.net/problem/UVA-11464

算法:暴力枚举n*n棋盘的第一行,然后递推地得出下面的每一行。

坑:暴力算法写错*3  orz

#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second

typedef double  db;
typedef long long ll;
const int MAXN = 20;;
const int maxn = MAXN;
const double eps = 1e-8;
const double PI = acos(-1.0);
const int INF = 1e9+10;
int n;
int a[maxn][maxn];
int b[maxn][maxn];
int check(int s) {
    int ret = 0;
    rep(i, 0, n-1) {
        if (((s&(1 << i)) != 0))b[1][i + 1] = 1; else b[1][i + 1] = 0;
        if (b[1][i + 1] == 0 && a[1][i + 1] == 1)return INF;
        else if (b[1][i + 1] != a[1][i + 1])ret++;
    }
    rep(i,2,n)
        rep(j, 1, n) {
        int prt = 0;
        //if (i - 2 < 1 || j - 1 < 1 || i + 1 > n)continue;
        if(i-1>=1&&j-1>=1)prt += b[i - 1][j - 1];
         if(i-1>=1&&j+1<=n)prt += b[i - 1][j + 1];
        if(i-2>=1)prt += b[i - 2][j];
        if (prt % 2 == 0) {
            if (a[i][j] == 1)return INF;
             b[i][j] = 0;
        }
        else {
            if (a[i][j] == 0)ret++,b[i][j]=1;
            else b[i][j] = 1;
        }
    }
    return ret;
}
int main() {
    int t;
    cin >> t;
    int kase = 0;
    while (t--) {
        cin >> n;
        rep(i, 1, n)rep(j, 1, n)cin >> a[i][j];
        int ans = INF;
        rep (s, 0, (1 << n) - 1) {
            ans = min(ans, check(s));
            
            
        }
        if (ans == INF)ans = -1;
        printf("Case %d: %d
", ++kase, ans);
    }
    //cin >> t;
}
/*
2
3
0 0 0
1 0 0
0 0 0


3
3
0 0 0
0 0 0
0 0 0
3
0 0 0
1 0 0
0 0 0
3
1 1 1
1 1 1
0 0 0




*/
View Code

 eg8 

套路:骰子类的题套路(polya的群)。pose处理:写程序打表记录所有状态,动态地写。

打表代码:

#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second

typedef double db;
typedef long long ll;
const int MAXN = 100010;;
const int maxn = 12e4;
const db eps = 1e-7;
const double PI = acos(-1.0);
int l[] = { 4,0,2,3,5,1 };
int up[] = { 2,1,5,0,4,3 };
void rot(int * T, int * p) {
    int q[6];
    memcpy(q, p, sizeof(q));
    rep(i, 0, 5)p[i] = T[q[i]];
}
void print() {
    int p0[6] = { 0,1,2,3,4,5 };
    printf("int dice24[24][6]={
");
    rep(i, 0, 5) {
        int p[6];
        memcpy(p, p0, sizeof(p0));
        if (i == 0)rot(up, p);
        if (i == 1)rot(l, p), rot(up, p);
        if (i == 2);
        if (i == 3)rot(up, p), rot(up, p);
        if (i == 4)rot(l, p), rot(l, p), rot(l, p), rot(up, p);
        if (i == 5)rot(l, p), rot(l, p), rot(up, p);
        rep(i, 0, 3) {
            printf("{%d, %d, %d, %d, %d, %d},
 ", p[0], p[1], p[2], p[3], p[4], p[5]);
            rot(l, p);
        }
    }
    printf("};
");
}
int main() {
    int n;
    print();
    cin >> n;
}
/*


*/
View Code

AC代码:

#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 100010;;
const int maxn = 1005;
const db eps = 1e-7;
map<string,int>names;
int dice[maxn][6];
int n,ans,r[maxn];
int color[maxn][6];
int idx = 0;
int dice24[24][6] = {
    { 2, 1, 5, 0, 4, 3 },
{ 2, 0, 1, 4, 5, 3 },
{ 2, 4, 0, 5, 1, 3 },
{ 2, 5, 4, 1, 0, 3 },
{ 4, 2, 5, 0, 3, 1 },
{ 5, 2, 1, 4, 3, 0 },
{ 1, 2, 0, 5, 3, 4 },
{ 0, 2, 4, 1, 3, 5 },
{ 0, 1, 2, 3, 4, 5 },
{ 4, 0, 2, 3, 5, 1 },
{ 5, 4, 2, 3, 1, 0 },
{ 1, 5, 2, 3, 0, 4 },
{ 5, 1, 3, 2, 4, 0 },
{ 1, 0, 3, 2, 5, 4 },
{ 0, 4, 3, 2, 1, 5 },
{ 4, 5, 3, 2, 0, 1 },
{ 1, 3, 5, 0, 2, 4 },
{ 0, 3, 1, 4, 2, 5 },
{ 4, 3, 0, 5, 2, 1 },
{ 5, 3, 4, 1, 2, 0 },
{ 3, 4, 5, 0, 1, 2 },
{ 3, 5, 1, 4, 0, 2 },
{ 3, 1, 0, 5, 4, 2 },
{ 3, 0, 4, 1, 5, 2 },
};

int ID(const char* name) {
    string s(name);
    if (names.count(s))return names[s];
    names[s] = ++idx; return names[s];
}
void check() {
    rep(i, 0, n-1)rep(j, 0, 5)color[i][dice24[r[i]][j]] = dice[i][j];
    int tot = 0;
    rep(j, 0, 5) {
        int cnt[maxn];
        mmm(cnt, 0);
        int maxface = 0;
        rep(i, 0, n-1)maxface = max(maxface, ++cnt[color[i][j]]);
        tot += n - maxface;
    }
    ans = min(ans, tot);
}
void dfs(int x) {
    if (x == n)check();
    else rep(i, 0, 23) {
        r[x] = i;
        dfs(x + 1);
    }
}
int main() {
    
    while (cin >> n && n)
    {
        names.clear(); idx = 0;
        rep(i, 0, n-1)rep(j, 0, 5) {
            char name[30];
            scanf("%s", name);
            dice[i][j] = ID(name);
        }
        ans = n * 6;
        r[0] = 0;
        dfs(1);
        cout << ans << endl;
    }
}
/*
3
scarlet green blue yellow magenta cyan
blue pink green magenta cyan lemon
purple red blue yellow cyan green
2
red green blue yellow magenta cyan
cyan green blue yellow magenta red
2
red green gray gray magenta cyan
cyan green gray gray magenta red
2
red green blue yellow magenta cyan
magenta red blue yellow cyan green
3
red green blue yellow magenta cyan
cyan green blue yellow magenta red
magenta red blue yellow cyan green
3
blue green green green green blue
green blue blue green green green
green green green green green sea-green
3
red yellow red yellow red yellow
red red yellow yellow red yellow
red red red red red red
4
violet violet salmon salmon salmon salmon
violet salmon salmon salmon salmon violet
violet violet salmon salmon violet violet
violet violet violet violet salmon salmon
1
red green blue yellow magenta cyan
4
magenta pink red scarlet vermilion wine-red
aquamarine blue cyan indigo sky-blue turquoise-blue
blond cream chrome-yellow lemon olive yellow
chrome-green emerald-green green olive vilidian sky-blue
0


4
2
0
0
2
3
4
4
0
16
*/
View Code

 eg9

套路:经典爆搜dfs。

#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 100010;;
const int maxn = 1005;
const db eps = 1e-7;
const char* mahjong[] = {
    "1T","2T","3T","4T","5T","6T","7T","8T","9T",
    "1S","2S","3S","4S","5S","6S","7S","8S","9S",
    "1W","2W","3W","4W","5W","6W","7W","8W","9W",
    "DONG","NAN","XI","BEI",
    "ZHONG","FA","BAI"
};
int convert(char *s) {
    REP(i, 0, 34) {
        if (strcmp(mahjong[i], s) == 0)return i;
    }
    return -1;
}
int cnt[34];
bool search(int dep) {
    REP(i, 0, 34)if (cnt[i] >= 3) {
        if (dep == 3)return 1;
        cnt[i] -= 3;
        if (search(dep + 1))return 1;
        cnt[i] += 3;
    }
    rep(i, 0, 24)if (i % 9 <= 6 && cnt[i] >= 1 && cnt[i + 1] >= 1 && cnt[i + 2] >= 1) {
        if (dep == 3)return 1;
        cnt[i] -= 1, cnt[i + 1] -= 1, cnt[i + 2] -= 1;
        if (search(dep + 1))return 1;
        cnt[i] += 1, cnt[i + 1] += 1, cnt[i + 2] += 1;
    }
    return 0;

}
bool check() {
    REP(i, 0, 34) if (cnt[i] >= 2) {
            cnt[i] -= 2;
            if (search(0))return 1;
            cnt[i] += 2;
    }
    return 0;
}
int main() {
    int kase = 0;
    char s[100];
    int mj[15];
    bool ok=0;
    while (cin >> s) {
        if (s[0] == '0')break;
        printf("Case %d:", ++kase);
        mj[0] = convert(s);
        rep(i, 1, 12) { cin >> s; mj[i] = convert(s); }
        ok = 0;
        REP(i, 0, 34) {
            mmm(cnt, 0);
            REP(j, 0, 13)cnt[mj[j]]++;
            if (cnt[i] >= 4)continue;
            cnt[i]++;
            if (check()) {
                ok = 1;
                cout << ' '<<mahjong[i];
            }
            cnt[i]--;
        }
        if (!ok)puts(" Not ready");
        else cout << endl;
    }

}
/*

*/
View Code

eg10:

https://cn.vjudge.net/problem/UVA-11384

int f(int n) {
    return n == 1 ? 1 : f(n / 2) + 1;
}
int smain()
{
    int n;
    while (cin >> n)cout << f(n) << endl;

    /*don't delete*/
    return 0;
}
View Code

算法:经典瞎搞(想法)题

ps:瞎搞入门啊

 eg11:

套路:构建递归函数。汉诺塔类问题从最大的那个盘子考虑。

#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 100010;;
const int maxn = 1005;
const db eps = 1e-7;
int start[maxn], finish[maxn];
ll f(int *P, int i, int final) {
    if (i == 0)return 0;
    if (P[i] == final)return f(P, i - 1, final);
    return f(P, i - 1, 6 - P[i] - final) + (1LL << (i - 1));
}
int main() {
    int kase = 0;
    int n;
    while (cin >> n && n) {
        rep(i, 1, n)cin >> start[i];
        rep(i, 1, n)cin >> finish[i];
        int k = n;
        while (k >= 1 && start[k] == finish[k])k--;
        long long ans = 0;
        if (k >= 1) {
            int other = 6 - start[k] - finish[k];
            ans = f(start, k - 1, other) + f(finish, k - 1, other) + 1;
        }
        printf("Case %d: %lld
", ++kase, ans);
    }

}
/*

*/
View Code

eg12:

套路:最小值最大用二分。用map里套vector简化代码。还有注意二分的两种写法(表示自己并不明白)。

坑:没买全 二分的判断函数要返回false,另外本题没有点明单调性(价格越高,品质越高) 虽然是常识,但也可能导致二分算法错(青岛的教训)

#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 100010;;
const int maxn = 1005;
const db eps = 1e-7;
map<string, vector<pair<int, int> > >mmp;
int n, b;
bool ok(int x) {
    int tot = 0;
    for (auto t : mmp) {
        int mn = 1e9 + 5;
        for (auto tt : t.second)if(tt.second>=x) {
            mn = min(mn, tt.first);
        }
        if (mn == 1e9 + 5)return false;
        tot += mn;
    }
    if (tot <= b)return true;
    else return false;
}
int main() {
    int T;
    cin >> T;
    while (T--) {
        mmp.clear();
        cin >> n >> b;
        int maxq = 0;
        rep(i, 1, n) {
            string s,ss;
            int p, q;
            cin >> s>>ss>>p>>q;
            maxq = max(maxq, q);
            mmp[s].push_back({ p,q });
        }
        
        int L = 0, R = maxq;
        while (L < R) {
            int mid = L + (R - L + 1) / 2;
            if (ok(mid))L = mid; else R = mid - 1;
        }
        cout << L << endl;
    }
    //cin >> T;
}
/*
1
18 800
processor 3500_MHz 66 5
processor 4200_MHz 103 7
processor 5000_MHz 156 9
processor 6000_MHz 219 12
memory 1_GB 35 3
memory 2_GB 88 6
memory 4_GB 170 12
mainbord all_onboard 52 10
harddisk 250_GB 54 10
harddisk 500_FB 99 12
casing midi 36 10
monitor 17_inch 157 5
monitor 19_inch 175 7
monitor 20_inch 210 9
monitor 22_inch 293 12
mouse cordless_optical 18 12
mouse microsoft 30 9
keyboard office 4 10

*/
View Code

eg13:

https://cn.vjudge.net/problem/UVALive-3635

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<ctime>
#include<string>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 5;
const int maxn = MAXN;
const long long MOD = 1e8 + 7;
#define rep(i,t,n)  for(int i =(t);i<=(n);++i)
#define per(i,n,t)  for(int i =(n);i>=(t);--i)
#define mmm(a,b) memset(a,b,sizeof(a))
int phi[MAXN], prime[MAXN];

int isntp[maxn];
void sieve(int n) {
    int m = (int)sqrt(n + 0.5);
    mmm(isntp, 0);
    rep(i, 2, m)if (!isntp[i])for (int j = i * i; j <= n; j += i)isntp[j] = 1;

}
int ans[maxn];

int smain();
#define ONLINE_JUDGE
int main() {

    //ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    FILE *myfile;
    myfile = freopen("C:\Users\acm-14\Desktop\test\b.in", "r", stdin);
    if (myfile == NULL)
        fprintf(stdout, "error on input freopen
");
    FILE *outfile;
    outfile = freopen("C:\Users\acm-14\Desktop\test\out.txt", "w", stdout);
    if (outfile == NULL)
        fprintf(stdout, "error on output freopen
");
    long _begin_time = clock();
#endif
    smain();
#ifndef ONLINE_JUDGE
    long _end_time = clock();
    printf("time = %ld ms.", _end_time - _begin_time);
#endif
    return 0;
}

double a[maxn];
int n, f;
bool ok(double x) {
    int cnt = 0;
    rep(i, 1, n) {
        cnt += floor(a[i] / x);
    }
    return cnt >= f;
}
int smain()
{
    int t; cin >> t;
    while (t--) {
        
        cin >> n >> f; f++;
        rep(i, 1, n)scanf("%lf", &a[i]),a[i]=a[i]*a[i]*acos(-1);
        double l = 0, r = 1e8*acos(-1);
        while (abs(l-r)> 1e-5) {
            double mid = (l + r) / 2;
            if (ok(mid))l = mid;
            else r = mid;
        }
        printf("%.5lf
", l);
    }
    return 0;
}
/*
4
3 3
4 3 3
1 24
5
10 5
1 4 2 3 4 5 6 5 4 2
*/
View Code

算法:经典eps二分,

坑点:输出cout会wa。改成了printf后忘记换行了orz

ps:第一发写完发现和书上代码基本一样!

eg14

https://cn.vjudge.net/problem/UVA-11520

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<ctime>
#include<string>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 5;
const int maxn = MAXN;
const long long MOD = 1e8 + 7;
#define rep(i,t,n)  for(int i =(t);i<=(n);++i)
#define per(i,n,t)  for(int i =(n);i>=(t);--i)
#define mmm(a,b) memset(a,b,sizeof(a))
int phi[MAXN], prime[MAXN];

int isntp[maxn];
void sieve(int n) {
    int m = (int)sqrt(n + 0.5);
    mmm(isntp, 0);
    rep(i, 2, m)if (!isntp[i])for (int j = i * i; j <= n; j += i)isntp[j] = 1;

}
int ans[maxn];

int smain();
#define ONLINE_JUDGE
int main() {

    //ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    FILE *myfile;
    myfile = freopen("C:\Users\acm-14\Desktop\test\b.in", "r", stdin);
    if (myfile == NULL)
        fprintf(stdout, "error on input freopen
");
    FILE *outfile;
    outfile = freopen("C:\Users\acm-14\Desktop\test\out.txt", "w", stdout);
    if (outfile == NULL)
        fprintf(stdout, "error on output freopen
");
    long _begin_time = clock();
#endif
    smain();
#ifndef ONLINE_JUDGE
    long _end_time = clock();
    printf("time = %ld ms.", _end_time - _begin_time);
#endif
    return 0;
}

string s[11];
int cnt[256];
int n;
char get(int x,int y) {
    mmm(cnt, 0);
    char ret = 0;
    rep(i,-1,1)
        rep(j, -1, 1)if(abs(i)+abs(j)<2) {
        int dx = x + i, dy = y + j;
        if (dx >= 0 && dx < n&&dy >= 0 && dy < n) {
            //if (s[dx][dy] == '.')ret = max((int)ret, 'A' - 1);
            cnt[s[dx][dy]]++;
        }
    }
    rep(i, 'A', 'Z')if (!cnt[i])return i;
    
}
int smain()
{
    int t; cin >> t;
    int kase = 0;
    while (t--) {
        printf("Case %d:
", ++kase);
         cin >> n;
        rep(i, 0, n-1) {
            cin >> s[i];
        }
        rep(i, 0, n-1) 
            rep(j, 0, n-1)if(s[i][j]=='.') {
             s[i][j] = get(i,j);
        }
        rep(i, 0, n-1)cout << s[i] << endl;
    }
    return 0;
}
/*
3
3
..B
...
...
3
B..
...
..A


3
3
...
.C.
Z..
3
...
A.X
...

*/
View Code

算法:了解一下字典序,书上的get函数有一点剪枝的

坑点:string输入 循环是到n-1!

ps:Morass 大佬也刷uva, 另外uva不把文件输入删掉也能ac啊?

eg15 

https://cn.vjudge.net/problem/UVALive-3902

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<ctime>
#include<string>
#include<vector>
using namespace std;
typedef long long ll;
const int MAXN = 1e3 + 5;
const int maxn = MAXN;
const long long MOD = 1e8 + 7;
#define rep(i,t,n)  for(int i =(t);i<=(n);++i)
#define per(i,n,t)  for(int i =(n);i>=(t);--i)
#define mmm(a,b) memset(a,b,sizeof(a))
int phi[MAXN], prime[MAXN];

int isntp[maxn];
void sieve(int n) {
    int m = (int)sqrt(n + 0.5);
    mmm(isntp, 0);
    rep(i, 2, m)if (!isntp[i])for (int j = i * i; j <= n; j += i)isntp[j] = 1;

}
int ans[maxn];

int smain();
#define ONLINE_JUDGE
int main() {

    //ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
    FILE *myfile;
    myfile = freopen("C:\Users\acm-14\Desktop\test\b.in", "r", stdin);
    if (myfile == NULL)
        fprintf(stdout, "error on input freopen
");
    FILE *outfile;
    outfile = freopen("C:\Users\acm-14\Desktop\test\out.txt", "w", stdout);
    if (outfile == NULL)
        fprintf(stdout, "error on output freopen
");
    long _begin_time = clock();
#endif
    smain();
#ifndef ONLINE_JUDGE
    long _end_time = clock();
    printf("time = %ld ms.", _end_time - _begin_time);
#endif
    return 0;
}

vector<int> E[maxn], nodes[maxn];
int n, s, k, fa[maxn];
bool covered[maxn];
void dfs(int u, int f, int d) {
    fa[u] = f;
    int nc = E[u].size();
    if (nc == 1 && d > k)nodes[d].push_back(u);

    for (int i = 0; i < nc; i++) {
        int v = E[u][i];
        if (v != f)dfs(v, u, d + 1);
    }
}
void dfs2(int u, int f, int d) {
    covered[u] = 1;
    int nc = E[u].size();

    for (int i = 0; i < nc; i++) {
        int v = E[u][i];
        if (v != f && d < k)dfs2(v, u, d + 1);
        
    }
}
int solve() {
    int ans = 0;
    mmm(covered, 0);
    for(int d=n-1;d>k;d--)
        for (int i = 0; i < nodes[d].size(); i++) {
            int u = nodes[d][i];
            if (covered[u])continue;

            int v = u;
            for (int j = 0; j < k; j++)v = fa[v];
            dfs2(v, -1, 0);
            ans++;
        }
    return ans;
}
int smain()
{
    int t; cin >> t;
    while (t--)
    {
        cin >> n >> s >> k;
        rep(i, 1, n)E[i].clear(), nodes[i].clear();
        rep(i, 1, n-1) {
            int x, y;
            cin >> x >> y;
            E[x].push_back(y);
            E[y].push_back(x);
        }
        dfs(s, -1, 0);
        cout << solve() << endl;
    }
    cin >> t;
    return 0;
}
/*
2 14
12 2
1 2
2 3
3 4
4 5
5 6
7 5
8 5
4 9
10 3
2 12
12 14
13 14
14 11
14
3 4
1 2
2 3
3 4
4 5
5 6
7 5
8 5
4 9
10 3
2 12
12 14
13 14
14 11
*/
View Code

算法:树上贪心dfs暴力

ps:蓝书的代码还是舒服啊

 eg16

套路:想法+二分题收尾。二分是礼物种类越多越能满足分礼物约束,

想法1是:先让第一个人取[1,a[i] ] 的礼物,然后在不取前一个人的前提下,偶数尽量往前取,奇数往后取,这样(当总人数为奇数时)最后一个是往后取的,判一下他有没有取到[1,a[i] ]的礼物就行。

想法2是:如果我们建一个vis数组表示前一个人拿了几个,那算法就n^2logn 了 。我们考虑每一个人具体选了哪些不重要,重要的是选了几个,more precisely,要表达尽量往前取和往后取,我们只要把礼物分成前半部分与后半部分,以a[1]为分界,这样二分的judge函数就变成线性了

#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 100010;;
const int maxn = 1e5+5;
const db eps = 1e-7;

int n, b;
int a[maxn];
int vis[maxn] ;
int l[maxn], r[maxn];
bool ok(int p) {
    int x = a[1], y = p - x;
    l[1] = x; r[1] = 0;
    rep(i, 2, n) {
        if (i % 2 == 0)
        {
            l[i] = min(x - l[i - 1],a[i]);
            r[i] = a[i] - l[i];
        }
        else {
            r[i] = min(a[i], y - r[i - 1]);
            l[i] = a[i] - r[i];
        }
        
    }
    return l[n] == 0;
    
}


int main() {
    
    while (cin >> n && n) {
        
        int maxa=0;
        rep(i, 1, n)scanf("%d", &a[i]),maxa=max(maxa,a[i]);
        if (n == 1)cout << a[1] << endl;
        else{
            int ans = a[n] + a[1];
            rep(i, 1, n - 1)ans = max(ans, a[i] + a[i + 1]);
            
        
        
            int L = ans, R = maxa*4;
            if (n % 2) {
                while (L <= R) {

                    int mid = L + R >> 1;
                    if (ok(mid))R = mid - 1; else L = mid + 1;
                }
            }
            cout << L << endl;
        }
    }
        
        
        
    
    //cin >> T;
}
View Code

eg17

加速:计数排序

#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 100010;;
const int maxn = 1e5+5;
const db eps = 1e-7;

int cnt[101];
int n;

int main() {

    while (cin >> n && n) {
        int x;
        mmm(cnt, 0);
        rep(i, 1, n) {
            scanf("%d", &x); cnt[x]++;
        }
        int first = 1;
        rep(i, 1, 100) {
            while (cnt[i]--) {
                if (first)printf("%d", i), first = 0;
                else printf(" %d", i);
            }
        }
        cout << endl;


        //cin >> T;
    }
}
/*


*/
View Code

eg18

加速:线性算法。O(1)存储动态维护max

#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 100010;;
const int maxn = 1e5+5;
const db eps = 1e-7;

int cnt[101];
int n;

int main() {

    int T;
    cin >> T;
    while(T--){
        int n;
        cin >> n;
        int a;
        
        int ans = -1e9;
        cin >> a;
        int maxa = a;
        rep(i, 2, n) {
            cin >> a;
            ans = max(ans, maxa - a);
            maxa = max(maxa, a);
        }
        cout << ans << endl;
        //cin >> T;
    }
    //cin >> T;
}
/*



*/
View Code

 eg19

加速:stl找循环节,截取技巧。

套路:floyd判圈找循环节:比set快,O(1)。

#include<algorithm>
#include<iostream>
#include<sstream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 100010;;
const int maxn = 1e5+5;
const db eps = 1e-7;

int cnt[101];
int n;
int next(int n, int k) {
    stringstream ss;
    ss << (long long)k*k;
    string s = ss.str();
    if (s.length() > n)s = s.substr(0, n);
    int ans;
    stringstream ss2(s);
    ss2 >> ans;
    return ans;
}
set<int>S;
int main() {

    int T;
    cin >> T;
    while(T--){
        int n,k;
        cin >> n>>k;
        S.clear();
        int ans = k;
        while (!S.count(k)) {
            S.insert(k);
            k = next(n, k);
            ans = max(ans, k);
        }
        cout << ans << endl;
    }
    //cin >> T;
}
/*
2
1 6
2 99


*/
View Code
#include<algorithm>
#include<iostream>
#include<sstream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 100010;;
const int maxn = 1e5+5;
const db eps = 1e-7;

int cnt[101];
int n;
int next(int n, int k) {
    stringstream ss;
    ss << (long long)k*k;
    string s = ss.str();
    if (s.length() > n)s = s.substr(0, n);
    int ans;
    stringstream ss2(s);
    ss2 >> ans;
    return ans;
}
set<int>S;
int main() {

    int T;
    cin >> T;
    while(T--){
        int n,k;
        cin >> n>>k;
        S.clear();
        int k1 = k, k2 = k;
        int ans = k;
        do {
            k1 = next(n, k1);
            k2 = next(n, k2); ans = max(ans, k2); k2 = next(n, k2); ans = max(ans, k2);
        } while (k1 != k2);
        cout << ans << endl;
    }
    //cin >> T;
}
View Code

一下是一系列递推维护区间(一维二维三维,单调性)信息的线性优化。,可以说是dp了

 eg20

加速:线性找区间某点最大覆盖线段数。

套路:解不等式组

#include<algorithm>
#include<iostream>
#include<sstream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 100010;;
const int maxn = 1e5+5;
const db eps = 1e-7;
//0<x+at<w
void update(int x, int a, int w, double& L, double& R) {
    if (a == 0) {
        if (x <= 0 || x >= w)R = L - 1;
    }
    else if (a > 0) {
        L = max(L, -(double)x / a);
        R = min(R, (double)(w - x) / a);
    }
    else {
        L = max(L, (double)(w-x) / a);
        R = min(R, -(double)x / a);
    }
}
struct Event {
    double x;
    int type;
    bool operator <(const Event& a) const {
        return x < a.x || (x == a.x&&type > a.type);
    }
}events[maxn*2];
int main() {

    int T;
    cin >> T;
    while(T--){
        int w, h, n, e = 0;
        scanf("%d%d%d", &w, &h, &n);
        for (int i = 0; i < n; i++) {
            int x, y, a, b;
            scanf("%d%d%d%d", &x, &y, &a, &b);
            double L = 0, R = 1e9;
            update(x, a, w, L, R);
            update(y, b, h, L, R);
            if (R > L) {
                events[e++] = { L, 0 };
                events[e++]=  { R, 1 };
            }
        }
        sort(events, events + e);
        int cnt = 0;
        int ans = 0;
        REP(i, 0, e) {
            if (events[i].type == 0)ans = max(ans, ++cnt);
            else cnt--;
        }
        cout << ans << endl;
    }
    cin >> T;
}
/*
2
4 2
2
-1 1 1 -1
5 2 -1 -1
13 6
7
3 -2 1 3
6 9 -2 -1
8 0 -1 -1
7 6 10 0
11 -2 2 1
-2 4 6 -1
3 2 -5 -1


*/
View Code

eg21

加速:利用单调性,二分nlogn 再到线性 n

#include<algorithm>
#include<iostream>
#include<sstream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 100010;;
const int maxn = 1e5+5;
const db eps = 1e-7;
//0<x+at<w
int a[maxn],s[maxn];
int main() {
    int n, S;
    
    while (cin >> n >> S) {
        int ans = 1e6;
        rep(i, 1, n)scanf("%d", &a[i]);
        rep(i, 1, n)s[i] = s[i - 1] + a[i];
        rep(j, 1, n) {
            int i = lower_bound(s, s + j, s[j] - S) - s;
            if (i > 0)ans = min(ans, j - i + 1);
        }
        if (ans == 1e6)ans = 0;
        cout << ans<<endl;
    }
}
/*
10 15
5 1 3 5 10 7 4 9 2 8
5 11
1 2 3 4 5



*/
View Code
#include<algorithm>
#include<iostream>
#include<sstream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 100010;;
const int maxn = 1e5+5;
const db eps = 1e-7;
//0<x+at<w
int a[maxn],s[maxn];
int main() {
    int n, S;
    
    while (cin >> n >> S) {
        int ans = 1e6;
        rep(i, 1, n)scanf("%d", &a[i]);
        rep(i, 1, n)s[i] = s[i - 1] + a[i];
        int i = 1;
        rep(j, 1, n) {
            if (s[i - 1] > s[j] - S)continue;
            while (s[i] < s[j] - S)i++;
            ans = min(ans,j - i + 1);
        }
        if (ans == 1e6)ans = 0;
        cout << ans<<endl;
    }
}
/*
10 15
5 1 3 5 10 7 4 9 2 8
5 11
1 2 3 4 5



*/
View Code

eg22

加速:维护二维网格里的最大矩阵:维护每个各点向上延申最远点,以及这条线段左右移动的最远点。

#include<algorithm>
#include<iostream>
#include<sstream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 1010;;
const int maxn = 1e3+5;
const db eps = 1e-7;

int a[maxn],s[maxn];
int mat[maxn][maxn], up[maxn][maxn], l[maxn][maxn], r[maxn][maxn];
int main() {
    int t; cin >> t; while (t--) {
        int n, m;
        cin >> n >> m;
        rep(i, 1, n)
            rep(j, 1, m) {
            char c = getchar();
            while (c != 'F'&&c != 'R') { c = getchar(); }
            mat[i][j] = c == 'F' ? 0 : 1;
        }
        int ans = 0;
        rep(i, 1, n) {
            int lo = 0, ro = m+1;
            rep(j, 1, m)if (mat[i][j] == 1)up[i][j] = l[i][j] = 0, lo = j;
            else {
                up[i][j] = i == 1 ? 1 : up[i - 1][j] + 1;
                l[i][j] = i == 1 ? lo + 1 : max(l[i - 1][j], lo + 1);
            }
            per(j, m, 1) if (mat[i][j] == 1)r[i][j] = m + 1, ro = j; else {
                r[i][j] = i == 1 ? ro - 1 : min(r[i - 1][j], ro - 1);
                ans = max(ans, up[i][j] * (r[i][j] - l[i][j] + 1));
            }
        }
        cout << ans * 3<<endl;
    }
    //cin >> t;
}
/*
2
5 6
R F F F F F
F F F F F F
R R R F F F
F F F F F F
F F F F F F
5 5
R R R R R
R R R R R
R R R R R
R R R R R
R R R R R


*/
View Code

 eg23

题意:给你一堆点,计算在一个矩形边长上的点数最大值。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      

加速:y坐标离散化。把矩形拆成两条横线两条竖线。横线用前缀和维护,竖线暴力维护。线性时间,再加上枚举上下界,O(n^3).

#include<algorithm>
#include<iostream>
#include<sstream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 110;;
const int maxn = 1e2+5;
const db eps = 1e-7;
struct Point {
    int x, y;
    bool operator<(const Point& a)const {
        return x < a.x;
    }
}p[maxn];
int n, m, y[maxn], on[maxn], on2[maxn], l[maxn];
int solve() {
    sort(p, p + n);
    sort(y, y + n);
    m = unique(y, y + n) - y;//离散化
    if (m <= 2)return n;
    int ans = 0;
    REP(a, 0, m)
        REP(b, a + 1, m) {
        int ymin = y[a], ymax = y[b];

        int k = 0;
        REP(i, 0, n) {
            if (i == 0 || p[i].x != p[i - 1].x) {
                k++;
                on[k] = on2[k] = 0;
                l[k] =  l[k - 1] + on2[k - 1] - on[k - 1];
            }
            if (p[i].y > ymin&&p[i].y < ymax) on[k]++;
            if (p[i].y >= ymin && p[i].y <= ymax) on2[k]++;
        }
        if (k <= 2)return n;
        
        int M = 0;
        rep(j, 1, k) {
            ans = max(ans, l[j] + on2[j] + M);
            M=max(M, on[j] - l[j]);
        }
    }
    return ans;
}
int main() {
    int kase = 0;
    while (cin >> n && n)
    {
        REP(i, 0, n) { cin >> p[i].x >> p[i].y; y[i] = p[i].y; }
        printf("Case %d: %d
", ++kase, solve());
    }
}
/*
10
2 3
9 2
7 4
3 4
5 7
1 5
10 4
10 6
11 4
4 6
0



*/
View Code

 eg24

加速:三维前缀和 , 具体原理也不怎么明白,当个板子用就好了

#include<algorithm>
#include<iostream>
#include<sstream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 30;;
const int maxn = 1e2+5;
const db eps = 1e-7;
ll S[maxn][maxn][maxn];
ll INF = 1ll << 60;
void expand(int i, int& b0, int& b1, int& b2) {
    b0 = i & 1; i >>= 1;
    b1 = i & 1; i >>= 1;
    b2 = i & 1;
}
int sign(int b0, int b1, int b2) {
    return (b0 + b1 + b2) % 2 == 1 ? 1 : -1;
}
ll sum(int x1, int x2, int y1, int y2, int z1, int z2) {
    int dx = x2 - x1 + 1; int dy = y2 - y1 + 1; int dz = z2 - z1 + 1;
    ll s = 0;
    rep(i, 0, 7) {
        int b0, b1, b2;
        expand(i, b0, b1, b2);
        s -= S[x2 - b0 * dx][y2 - b1 * dy][z2 - b2 * dz] * sign(b0, b1, b2);
    }
    return s;
}
int main() {
    int t; cin >> t;
    while (t--) {
        int a, b, c, b1, b2, b0;
        cin >> a >> b >> c;
        mmm(S, 0);
        rep(x, 1, a)rep(y, 1, b)rep(z, 1, c)scanf("%lld", &S[x][y][z]);
        rep(x, 1, a)rep(y, 1, b)rep(z, 1, c)rep(i, 1, 7) {
            expand(i, b0, b1, b2);
            S[x][y][z] += S[x - b0][y - b1][z - b2] * sign(b0, b1, b2);
        }
        
        long long ans = -INF;
        rep(x1, 1, a)rep(x2, x1, a)rep(y1,1,b)rep(y2, y1, b) {
            long long M = 0;
            rep(z, 1, c) {
                long long s = sum(x1, x2, y1, y2, 1, z);
                ans = max(ans, s - M);
                M = min(M, s);
            }
        }
        cout << ans << endl;
        if (t)cout << endl;
    }
    //cin >> t;
}
/*
1
2 2 2
-1 2 0 -3 -2 -1 1 5


*/
View Code

eg25

套路:用异或和压缩字符串,然后状压地2^n暴力,用map降低复杂度(中途相遇)O(2^(N/2)*logn)

#include<algorithm>
#include<iostream>
#include<sstream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 30;;
const int maxn = 24;
const db eps = 1e-7;

map<int, int>table;
int bitcount(int x) { return x == 0 ? 0 : bitcount(x /2) + (x & 1); }//popcount
int A[maxn];
int main() {
    int n;
    while (cin >> n) {
        REP(i, 0, n) {
            string s; cin >> s;
            A[i] = 0;
            for (auto t : s) {A[i] ^= (1 << (t - 'A'));}
        }
        table.clear();
        int n1 = n / 2, n2 = n - n1;
        for (int i = 0; i < (1 << n1); i++) {
            int x = 0;
            REP(j, 0, n1)if (i & (1 << j))x ^= A[j];
            if (!table.count(x) || bitcount(table[x]) < bitcount(i))table[x] = i;
        }
        int ans = 0;
        for (int i = 0; i < (1 << n2); i++) {
            int x = 0;
            for (int j = 0; j < n2; j++)if (i&(1 << j))x ^= A[n1+j];
            if (table.count(x) && bitcount(ans) < bitcount(table[x]) + bitcount(i))ans = (i << n1) ^ table[x];
        }
        cout << bitcount(ans) << endl;
        REP(i, 0, n)if (ans&(1 << i))cout << i + 1<<' ';
        cout << endl;
        
    }
    //cin >> t;
}
/*
1
ABC
6
ABD
EG
GE
ABE
AC
BCD

*/
View Code

 eg26

dp:约瑟夫递推地做

#include<algorithm>
#include<iostream>
#include<sstream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 30;;
const int maxn = 1e4+2;
const db eps = 1e-7;
int f[maxn];
int main() {
    int n, m, k;
    while (cin >> n >> k >> m && n) {
        f[1] = 0;
        rep(i, 2, n)f[i] = (f[i - 1] + k) % i;
        int ans = (m - k + 1 + f[n]) % n;
        if (ans <= 0)ans += n;
        cout << ans << endl;
    }
}
/*
8 5 3
100 9999 98
10000 10000 10000
0 0 0

*/
View Code

eg27

dp:LCS转化为LIS 具体做法是对第一个序列离散化,然后在第二个里LIS

#include<algorithm>
#include<iostream>
#include<sstream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 30;;
const int maxn = 250*250+2;
const int INF = 1e9;
const db eps = 1e-7;
int S[maxn], g[maxn], d[maxn];
int num[maxn];
int main() {
    int T;
    cin >> T;
    rep(k, 1, T) {
        int N, p, q, x;
        cin >> N >> p >> q;
        rep(i, 1, p + 1) { scanf("%d", &x); num[x] = i; }
        int n = 0;
        rep(i, 0, q) {
            scanf("%d", &x); if (num[x])S[n++] = num[x];
        }
        rep(i, 1, n)g[i] = INF;
        int ans = 0;
        REP(i, 0, n) {
            int k = lower_bound(g + 1, g + n + 1, S[i]) - g;
            d[i] = k;
            g[k] = S[i];
            ans = max(ans, d[i]);

        }
        printf("Case %d: %d
", k, ans);
    }
}
/*
1
3 6 7
1 7 5 4 8 3 9
1 4 3 5 6 2 8 9

*/
View Code

eg28

dp:d(i,j)=sum(i,j)-min{rep(x,i+1,j)d(x,j);per(x,j-1,i)d(i,x);0;}.

优化:区间N*N dp 预处理成O(N)

记忆化搜索:

#include<algorithm>
#include<iostream>
#include<sstream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 30;;
const int maxn = 100+2;
const int INF = 1e9;
const db eps = 1e-7;
int n;
int S[maxn], A[maxn], d[maxn][maxn], vis[maxn][maxn];
int dp(int i, int j) {
    if (vis[i][j])return d[i][j];
    vis[i][j] = 1;
    int m = 0;
    rep(k, i + 1, j)m = min(m, dp(k,j));
    rep(k, i, j - 1)m = min(m, dp(i, k));
    d[i][j] = S[j] - S[i - 1] - m;
    return d[i][j];
}
int main() {
    while (cin >> n && n) {
        S[0] = 0;
        rep(i, 1, n){
            cin >> A[i]; S[i] = S[i - 1] + A[i];
        }
        mmm(vis, 0);
        cout << 2 * dp(1, n) - S[n] << endl;;
    }

}
/*
4
4 -10 -20 7
4
1 2 3 4
0

*/
View Code

预处理:

#include<algorithm>
#include<iostream>
#include<sstream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 30;;
const int maxn = 100+2;
const int INF = 1e9;
const db eps = 1e-7;
int n;
int S[maxn], A[maxn], d[maxn][maxn], vis[maxn][maxn];
int f[maxn][maxn], g[maxn][maxn];
int dp(int i, int j) {
    if (vis[i][j])return d[i][j];
    vis[i][j] = 1;
    int m = 0;
    rep(k, i + 1, j)m = min(m, dp(k,j));
    rep(k, i, j - 1)m = min(m, dp(i, k));
    d[i][j] = S[j] - S[i - 1] - m;
    return d[i][j];
}
int main() {
    while (cin >> n && n) {
        S[0] = 0;
        rep(i, 1, n){
            cin >> A[i]; S[i] = S[i - 1] + A[i];
        }
        rep(i, 1, n)f[i][i] = g[i][i] = d[i][i] = A[i];
        rep(len, 1, n)
            rep(i, 1, n - len) {
            int j = i + len;
            int m = 0;
            m = min(m, f[i + 1][j]);
            m = min(m, g[i][j - 1]);
            d[i][j] = S[j] - S[i - 1] - m;
            f[i][j] = min(d[i][j], f[i + 1][j]);
            g[i][j] = min(d[i][j], g[i][j - 1]);

        }
        //mmm(vis, 0);
        //cout << 2 * dp(1, n) - S[n] << endl;;
        cout << 2 * d[1][n] - S[n] << endl;;
    }

}
/*
4
4 -10 -20 7
4
1 2 3 4
0

*/
View Code

eg29

存储方法:状压集合,
dp:f(S)=max{f(S-S0)|S0是S的子集,cover[S0]为全集}+1;

#include<algorithm>
#include<iostream>
#include<sstream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 30;;
const int maxn = 100+2;
const int INF = 1e9;
const db eps = 1e-7;

int P[20];
int cover[(1<<20)];
int f[(1 << 20)];
int n;
int kase = 0;
int main() {
    while (cin >> n && n) {
        REP(i, 0, n) {
            int m, x;
            scanf("%d", &m);
            P[i] = 1 << i;
            while (m--) { scanf("%d", &x); P[i] |= (1 << x); }
        }
        REP(S, 0, (1 << n)) {
            cover[S] = 0;
            REP(i, 0, n) {
                if (S&(1 << i))cover[S] |= P[i];
            }
        }
        f[0] = 0;
        int ALL = (1 << n) - 1;
        rep(S, 1, (1 << n) - 1) {
            f[S] = 0;
            for (int S0 = S; S0; S0 = (S0 - 1)&S)
                if (cover[S0] == ALL)f[S] = max(f[S], f[S^S0] + 1);
        }
        printf("Case %d: %d
", ++kase, f[ALL]);
    }


}
/*
3
2 1 2
2 0 2
2 0 1
4
1 1
1 0
1 3
1 2
0


*/
View Code

eg30 

双目标优化+树形dp

dp方程比较复杂。

#include<algorithm>
#include<iostream>
#include<sstream>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<string>
#include<ctime>
#include<stack>
#include<map>
#include<set>
#include<list>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define REP(i,j,k) for(int i = (int)j;i < (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
//#define x first
//#define y second
typedef double db;
typedef long long ll;
const int MAXN = 30;;
const int maxn = 100+2;
const int INF = 1e9;
const db eps = 1e-7;
vector<int> adj[1010];
int vis[1010][2], d[1010][2], n, m;
int dp(int i, int j, int f) {
    if (vis[i][j])return d[i][j];
    vis[i][j] = 1;
    int & ans = d[i][j];
    ans = 2000;
    for (int k = 0; k < adj[i].size(); k++)
        if (adj[i][k] != f)ans += dp(adj[i][k], 1, i);
    if (!j&&f >= 0)ans++;

    if (j || f < 0) {
        int sum = 0;
        for (int k = 0; k < adj[i].size(); k++)if (adj[i][k] != f)
            sum += dp(adj[i][k], 0, i);
        if (f >= 0)sum++;
        ans = min(ans, sum);
    }
            
            
    
    return ans;
    
}
int main() {
    int T, a, b;
    cin >> T;
    while (T--) {
        cin >> n >> m;
        REP(i, 0, n)adj[i].clear();
        REP(i, 0, m) {
            cin >> a >> b;
            adj[a].push_back(b);
            adj[b].push_back(a);
        }
        mmm(vis, 0);
        int ans = 0;
        REP(i, 0, n)if (!vis[i][0])ans += dp(i, 0, -1);
        cout << ans / 2000 << ' ' << m - ans % 2000 << ' ' << ans % 2000<<endl;
    }


}
/*
2
4 3
0 1
1 2
2 3
5 4
0 1
0 2
0 3
0 4


*/
View Code

 eg

成功的路并不拥挤,因为大部分人都在颓(笑)
原文地址:https://www.cnblogs.com/SuuT/p/9925527.html