F - Kings on a Chessboard
国王周围的八个格子不可以再放国王(但是国王可以挨着边界),问在给定大小的棋盘有多少种方法可以放k个国王。
和
POJ 2411 是一模一样的做法。
有两个注意点:
1.国王最多可以放(x + 1) * (y + 1) / 4个,所以国王最多只可能放64个;
2.国王是可以挨着墙壁的,所以设计状态的时候到了最后还剩一个位置时可以再放个国王。
#pragma comment(linker, "/STACK:102400000, 102400000") #include <algorithm> #include <iostream> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <math.h> using namespace std; #define OT printf #define MOD 1000000007 #define LL long long #define MAXN (1 << 16) + 10 #define RUN(x) freopen(#x, "r", stdin); #define REP(i, n) for(i = 0; i < n; i++) #define FOR(i, s, e) for(i = s; i < e; i++) inline int RD(int &x) { x = 0; char ch = getchar(); while(ch < '0' || ch > '9') { ch = getchar(); if(ch == EOF) return 0; } while(ch >= '0' && ch <= '9') { x *= 10; x += ch - '0'; ch = getchar(); } return 1; } inline int RD(int &x0, int &x1, int &x2) { return RD(x0) + RD(x1) + RD(x2); } /*..........................................dizzy............................................*/ bool vis[MAXN]; int cnt[MAXN]; int sta[16 * MAXN][2]; int x, y, k, tot; int dp[2][MAXN][65]; void dfs(int l, int now, int pre, int nk, int pk) { if((nk + pk > k)) return ; if(l > y) return ; if(l == y) { cnt[now] = nk, cnt[pre] = pk; sta[tot][0] = pre; sta[tot++][1] = now; } if(l == y - 1) { dfs(l + 1, (now | 1) << 1, pre << 1, nk + 1, pk); dfs(l + 1, now << 1, (pre | 1) << 1, nk, pk + 1); } dfs(l + 2, (now | 1) << 2, pre << 2, nk + 1, pk); dfs(l + 2, now << 2, (pre | 1) << 2, nk, pk + 1); dfs(l + 1, now << 1, pre << 1, nk, pk); } //int getk(int x) //{ // int ans = 0; // while(x) // { // if(x & 1) ans++; // x = x >> 1; // } // return ans; //} int work() { if((x + 1) / 2 * (y + 1) / 2 < k) return 0; int i, j, c; LL ret = 0; tot = 0; dfs(0, 0, 0, 0, 0); // REP(i, tot) cout << sta[i][0] << ' ' << sta[i][1] << endl; memset(dp, 0, sizeof(dp)); dp[0][0][0] = 1; FOR(i, 1, x + 1) { memset(dp[i % 2], 0, sizeof(dp[i % 2])); REP(j, tot) REP(c, k + 1) { if(cnt[sta[j][1]] + c <= k) { dp[i % 2][sta[j][1]][cnt[sta[j][1]] + c] += dp[(i - 1) % 2][sta[j][0]][c]; dp[i % 2][sta[j][1]][cnt[sta[j][1]] + c] %= MOD; } } } memset(vis, true, sizeof(vis)); REP(i, tot) { if(vis[sta[i][1]]) { ret += dp[x % 2][sta[i][1]][k]; ret %= MOD; vis[sta[i][1]] = false; } } return ret; } int main() { // RUN(Kings_on_a_Chessboard.in); int t; RD(t); while(t--) { RD(x, y, k); if(x < y) swap(y, x); OT("%d\n", work()); } return 0; }
I - Space Travel
floyd + 三维上的线段最短距离。
#include <algorithm> #include <iostream> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <math.h> using namespace std; #define MAXN 110 #define eps 1e-8 int sig(double x) { return (x > eps) - (x < -eps); } typedef struct Point { double x, y, z; Point(double _x = 0.0, double _y = 0.0, double _z = 0.0): x(_x), y(_y), z(_z) {} double dis(const Point &argu) const { return sqrt((x - argu.x) * (x - argu.x) + (y - argu.y) * (y - argu.y) + (z - argu.z) * (z - argu.z)); } Point operator ^(const Point &argu) const { return Point(y * argu.z - z * argu.y, z * argu.x - x * argu.z, x * argu.y - y * argu.x); } double operator *(const Point &argu) const { return x * argu.x + y * argu.y + z * argu.z; } Point operator +(const Point &argu) const { return Point(x + argu.x, y + argu.y, z + argu.z); } Point operator -(const Point &argu) const { return Point(x - argu.x, y - argu.y, z - argu.z); } double len() const { return sqrt(x * x + y * y + z * z); } double dis_line(Point &a, Point &b) { return ((*this - a) ^ (b - a)).len() / (b - a).len(); } double dis_seg(Point &a, Point &b) { if(sig((*this - a) * (b - a)) >= 0 && sig((*this - b) * (a - b)) >= 0) return dis_line(a, b); return min(dis(a), dis(b)); } double V6(Point a, Point b, Point c) { return (((a - *this) ^ (b - *this)) * (c - *this)); } int side(Point &a, Point &b, Point &c) { return sig(V6(a, b, c)); } void in() { scanf("%lf%lf%lf", &x, &y, &z); } void out() { printf("%.10lf %.10lf %.10lf\n", x, y, z); } }Vector; Point pp[MAXN]; double dis[MAXN][MAXN]; double min(double a, double b) { if(sig(a - b) <= 0) return a; else return b; } double dis_line2(Point a1, Point b1, Point a2, Point b2) { Point v = (b1 - a1) ^ (b2 - a2); if(!sig(v.len())) return 0; return fabs((a2 - a1) * v) / v.len(); } double dis_seg2(Point a, Point b, Point c, Point d) { Point v = (b - a) ^ (d - c), o1 = a + v, o2 = c + v; if((c.side(o1, a, b) * d.side(o1, a, b) < 0) && (a.side(o2, c, d) * b.side(o2, c, d) < 0)) return dis_line2(a, b, c, d); else return min(min(a.dis_seg(c, d), b.dis_seg(c, d)), min(c.dis_seg(a, b), d.dis_seg(a, b))); } double work() { int n; scanf("%d", &n); n *= 2; n += 2; pp[0].in(); pp[n - 1].in(); for(int i = 1; i < n - 1; i ++) pp[i].in(); for(int i = 0; i < n; i++) dis[i][i] = 0.0; for(int i = 0; i < n; i++) for(int j = 0; j < i; j++) dis[i][j] = dis[j][i] = pp[i].dis(pp[j]); for(int i = 1; i < n - 1; i += 2) { dis[i][i + 1] = dis[i + 1][i] = 0.0; for(int j = 0; j < n; j++) { if(i == j || i + 1 == j) continue; double tmp = pp[j].dis_seg(pp[i], pp[i + 1]); dis[i][j] = dis[j][i] = min(dis[i][j], tmp); dis[i + 1][j] = dis[j][i + 1] = min(dis[i + 1][j], tmp); } } for(int i = 1; i < n - 1; i += 2) for(int j = 1; j < n - 1; j += 2) { if(i == j) continue; double tmp = dis_seg2(pp[i], pp[i + 1], pp[j], pp[j + 1]); dis[i][j] = dis[j][i] = min(dis[i][j], tmp); dis[i + 1][j] = dis[j][i + 1] = min(dis[i + 1][j], tmp); dis[i][j + 1] = dis[j + 1][i] = min(dis[i][j + 1], tmp); dis[i + 1][j + 1] = dis[j + 1][i + 1] = min(dis[i + 1][j + 1], tmp); } // for(int i = 0; i < n; i++) // { // for(int j = 0; j < n; j++) // printf("%11.8lf %d %d ", dis[i][j], i, j); // printf("\n"); // } for(int k = 0; k < n; k++) for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]); return dis[0][n - 1]; } int main() { // freopen("I.in", "r", stdin); // freopen("I.out", "w", stdout); int cas; scanf("%d", &cas); while(cas--) { printf("%.18lf\n", work()); } return 0; }
I - Dimensions
差点忘了这个恶模拟。。我实在是太弱了,写这道题以至于昏厥。。
以后一定要从全局考虑。。
#include <algorithm> #include <iostream> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <math.h> #include <map> using namespace std; #define MAXN 300 #define OT printf #define RUN(x) freopen(#x, "r", stdin); #define REP(i, n) for(i = 0; i < n; i++) #define FOR(i, s, e) for(i = s; i < e; i++) inline int RD(int &x) { x = 0; char ch = getchar(); while(ch < '0' || ch > '9') { ch = getchar(); if(ch == EOF) return 0; } while(ch >= '0' && ch <= '9') { x *= 10; x += ch - '0'; ch = getchar(); } return 1; } /*..........................................dizzy............................................*/ struct Unit { double num; int p[6]; Unit() {} void clr(void) { num = 1.0; memset(p, 0, sizeof(p)); } void out() { int i; OT("%.8lf ", num); REP(i, 6) OT("%d ", p[i]); puts(""); } bool operator ==(Unit &x) { int i; REP(i, 6) if(p[i] != x.p[i]) return false; return true; } Unit& operator +(const Unit &x) const { Unit sum = x; sum.num = num + x.num; return sum; } Unit& operator -(const Unit &x) const { Unit sum = x; sum.num = num - x.num; return sum; } Unit& operator *(const Unit &x) const { Unit sum; sum.num = num * x.num; int i; REP(i, 6) sum.p[i] = p[i] + x.p[i]; return sum; } }; Unit uu[MAXN]; const char Symbol[6][4] = {"m", "kg", "s", "A", "K", "cd"}; char un[MAXN][MAXN]; int tot; int srch(char *str) { int i; REP(i, tot) if(strcmp(un[i], str) == 0) return i; return -1; } char wrd[MAXN][MAXN]; char str[MAXN], stra[MAXN], strb[MAXN]; void init() { int i; REP(i, 6) { uu[i].clr(); uu[i].p[i] = 1; uu[i].num = 1.0; } REP(i, 6) strcpy(un[i], Symbol[i]); tot = 6; } inline int getWrd(char *str) { int cnt = 0, k = 0, i; int len = strlen(str); memset(wrd, 0, sizeof(wrd)); REP(i, len) { if(str[i] == ' ') wrd[cnt][k] = '\0', cnt++, k = 0, i++; wrd[cnt][k++] = str[i]; } // REP(i, cnt + 1) cout << wrd[i] << endl; return cnt; } inline void getUnit(int cnt, int id) { int s = 0; double w = 1.0; uu[id].clr(); int len0 = strlen(wrd[0]); if(isdigit(wrd[0][len0 - 1])) sscanf(wrd[0], "%lf", &w), s++; uu[id].num = w; int flag = 1, i, j, t; FOR(i, s, cnt + 1) { if(wrd[i][0] == '/') { flag = -1; continue; } double v = 1.0; int lenw = strlen(wrd[i]); if(isdigit(wrd[i][lenw - 1])) { wrd[i][lenw - 2] = '\0'; v = (double)(wrd[i][lenw - 1] - '0'); } int c = srch(wrd[i]); if(~c) { if(flag > 0) REP(t, v) uu[id].num *= uu[c].num; else REP(t, v) uu[id].num /= uu[c].num; REP(j, 6) { uu[id].p[j] += flag * v * uu[c].p[j]; } } } } inline bool ck1(char ch) { if(ch == '=') return true; return false; } inline bool ck2(int i) { if((str[i] == '+' || str[i] == '-' || str[i] == '*') && str[i + 1] == ' ') return true; return false; } void colUnit(int u) { int i, j; REP(i, u) { gets(str); int len = strlen(str); REP(j, len) if(ck1(str[j])) break; str[j - 1] = '\0'; int cnt = getWrd(str + j + 2); getUnit(cnt, tot); memset(str + j, 0, sizeof(str + j)); strcpy(un[tot], str); tot++; } } inline void put(int id) { int i; OT("%.6lf", uu[id].num); bool sub = false; REP(i, 6) { if(uu[id].p[i] < 0) sub = true; if(uu[id].p[i] > 0) { OT(" %s", Symbol[i]); if(uu[id].p[i] > 1) OT("^%d", uu[id].p[i]); } } if(sub) { OT(" /"); REP(i, 6) if(uu[id].p[i] < 0) { OT(" %s", Symbol[i]); if(uu[id].p[i] < -1) OT("^%d", -uu[id].p[i]); } } puts(""); } void work(int u, int n) { int i, j; char ch; bool flag = false; Unit &a = uu[MAXN - 1], &b = uu[MAXN - 2], &ans = uu[MAXN - 3]; a.clr(), b.clr(), ans.clr(); gets(str); int len = strlen(str); FOR(i, 1, len) if(ck2(i)) { flag = true; break; } if(flag) { strcpy(strb, str + i + 2); ch = str[i]; str[i - 1] = '\0'; int cnt = getWrd(strb); getUnit(cnt, MAXN - 2); memset(str + i, 0, sizeof(str + i)); } strcpy(stra, str); int cnt = getWrd(stra); getUnit(cnt, MAXN - 1); if(flag) { if(ch == '+') { if(a == b) { ans = (a + b); put(MAXN - 3); } else puts("Incompatible"); } if(ch == '-') { if(a == b) { ans = (a - b); put(MAXN - 3); } else puts("Incompatible"); } if(ch == '*') { ans = (a * b); put(MAXN - 3); } } else put(MAXN - 1); } int main() { // RUN(Dimensions.txt); // freopen("out_2.txt", "w", stdout); int u; while(RD(u)) { init(); colUnit(u); int i, n; RD(n); REP(i, n) work(u, n); } return 0; }