1004、Too Simple
自己在紙上模擬一下,其實可以找到一個規律,也就是找-1的個數n,然後答案爲(n-1)*m!(m爲每一層的方案數,因爲可以任意選)
然後記得沒有-1的時候要特判一下
AC代碼:
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <sstream>
#include <utility>
#include <iostream>
#include <algorithm>
#include <functional>
#define LL long long
#define INF 0x7fffffff
using namespace std;
#define MOD 1000000007
int n, m;
map<int, int> mp;
LL jie[105];
int a[105][105];
void init() {
jie[0] = 1;
for(int i = 1; i < 105; i ++) {
jie[i] = (jie[i-1] * i) % MOD;
}
}
LL get_pow(int x, int n) {
LL ret = 1;
for(int i = 0; i < n; i ++) {
ret = ret * jie[x] % MOD;
}
return ret;
}
bool fun(int m, int x, int p) {
if(m == 1) {
if(a[m][x] == p) return true;
else return false;
}
return fun(m-1, a[m][x], p);
}
int main() {
init();
//for(int i = 1; i<= 10; i ++) cout << jie[i] << " ";
while(scanf("%d %d", &n, &m) != EOF) {
int t;
int flag = 0;
int c = 0;
//int cnt = 0;
LL ans = 1;
for(int i = 1; i <= m; i ++) {
//cout << ans << endl;
mp.clear();
scanf("%d", &a[i][1]);
mp[a[i][1]] = 1;
if(a[i][1] != -1) {
//ans = (ans * get_pow(n, cnt-1)) % MOD;
//cnt = 0;
for(int j = 2; j <= n; j ++) {
scanf("%d", &a[i][j]);
if(mp[a[i][j]] == 1) {
flag = 1;
}
mp[a[i][j]] = 1;
}
}
else {
//cnt ++;
c ++;
}
}
ans = (ans * get_pow(n, c - 1)) % MOD;
int flag2 = 0;
if(c == 0) {
for(int i = 1; i <= n; i ++) {
if(!fun(m, i, i)) {
flag2 = 1;
break;
}
}
}
//cout << flag << " " << flag2 << endl;
if(flag == 1 || flag2 == 1) {
printf("0\n");
}
else printf("%I64d\n", ans);
}
return 0;
}
1007、Travelling Salesman Problem
題目傳送:HDU - 5402 - Travelling Salesman Problem
官方題解:
首先如果n爲奇數或者m爲奇數,那麼顯然可以遍歷整個棋盤。
如果n,m都爲偶數,那麼將棋盤黑白染色,假設(1,1)和(n,m)都爲黑色,那麼這條路徑中黑格個數比白格個數多11,而棋盤中黑白格子個數相同,所以必然有一個白格不會被經過,所以選擇白格中權值最小的不經過。
構造方法是這樣,首先RRRRDLLLLD這樣的路徑走到這個格子所在行或者上一行,然後DRUR這樣走到這個格子的所在列或者前一列,然後繞過這個格子。然後走完這兩行,接着按LLLLDRRRR這樣的路徑往下走。
這裏要注意必定需要走一個白格的情況,所以只需要不走那個權值最小的,按照不走權值最小的那個結點構造即可。
AC代碼:
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <sstream>
#include <utility>
#include <iostream>
#include <algorithm>
#include <functional>
#define LL long long
#define INF 0x7fffffff
using namespace std;
int mp[105][105];
int vis[105][105];
int n, m;
const int dx[] = {1, -1, 0, 0};
const int dy[] = {0, 0, 1, -1};
int main() {
while(scanf("%d %d", &n, &m) != EOF) {
int sum = 0;
int minx = INF, mini, minj;
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= m; j ++) {
scanf("%d", &mp[i][j]);
sum += mp[i][j];
if((i + j) & 1) {
if(minx > mp[i][j]) {
minx = mp[i][j];
mini = i;
minj = j;
}
}
}
}
string ans;
ans.clear();
if((n & 1) || (m & 1)) {
printf("%d\n", sum);
if(n & 1) {
int i, j;
for(i = 1; i <= n; i ++) {
for(j = 1; j < m; j ++) {
if(i & 1) ans += "R";
else ans += "L";
}
if(i != n) ans += "D";
}
}
else {
int i, j;
for(i = 1; i <= m; i ++) {
for(j = 1; j < n; j ++) {
if(i & 1) ans += "D";
else ans += "U";
}
if(i != m) ans += "R";
}
}
printf("%s\n", ans.c_str());
continue;
}
//cout << mini << " " << minj << endl;
memset(vis, 0, sizeof(vis));
printf("%d\n", sum - minx);
int i = 1, j = 1;//行和列
while(1) {
if(i == mini || i == mini - 1) break;
for(j = 1; j < m; j ++) {
if(i & 1) ans += "R";
else ans += "L";
}
if(i < n) ans += "D";
i ++;
}
if(i & 1) j = 1;
else j = m;
vis[i][j] = 1;
int bu = 2 * m - 2;
//cout << i << " " << j << endl;
int L = 1, R = m, U = i, D = i + 1;
while(bu --) {
for(int k = 0; k < 4; k ++) {
int x = i + dx[k];
int y = j + dy[k];
if(!vis[x][y] && x <= D && x >= U && y <= R && y >= L && !(x == mini && y == minj)) {
if(k == 0) ans += "D";
else if(k == 1) ans += "U";
else if(k == 2) ans += "R";
else if(k == 3) ans += "L";
vis[x][y] = 1;
i = x, j = y;
break;
}
}
}
//ans += " ";
i ++;
//cout << "hha" << endl;
if(i <= n) ans += "D";
while(i <= n) {
for(j = 1; j < m; j ++) {
if(i & 1) ans += "L";
else ans += "R";
}
if(i != n) ans += "D";
i ++;
}
printf("%s\n", ans.c_str());
}
return 0;
}