d572. 第六題:柏油我認識妳嗎之似曾不相識
內容 :
本題絕對是超越UVrongAnswer-online-judge,NPXC等……歷屆爛梗考古題的超級有梗題。
據某板中G姓要用弱者許胖在全國賽模式,難度調CRAZY(對手都是王X博)連續破台三次,才會有5%機率出現的隱藏人物有言:「這題是『世界宇宙無敵超級究極黃金必殺最強牛B好囧腹黑傲嬌三次方』的有梗題,若將該題目用來報科展絕對可以得到全國一等獎XDDDD。」
由於本題的梗實在太高了,只有智商>180才看得懂,智商低於100的人只要每天定期對本題膜拜個3次嘴裡大喊:「我是柏油控!」就能增加0.01%IQ。
題目敘述如下:
小蔡是一個柏油控,他擁有一塊矩形的私人柏油地,並由n條水平線及m條鉛直線分割成(m+1)*(n+1)塊等大的區域。
有一天小蔡想在不同區塊漆上四種不同的顏色,並規定相鄰的兩塊不能漆上同一顏色,兩個區塊被視為相鄰只有當兩區塊由一條共同的邊組成,且有些區塊會被指定為不漆顏色(其餘皆要漆色),請你計算出總共有幾種上色的方法?
輸入說明
:
輸入第一行為一個整數T(T<=50)表以下有幾組測資數。
一組測資將會從兩個整數M,N開始(0<=M,N<=6)為用來分割的鉛垂線數,及水平線數。
下一行為一個整數K表以下有幾個不用上色的格子座標。
接下來的K行為兩個整數x,y(1<=x<=M+1,1<=y<=N+1)及該格子的座標。
且每個座標都是唯一的不會重複。
輸出說明
:
範例輸入 :
2 1 1 1 2 1 0 0 0
範例輸出 :
Case 1: 36 Case 2: 4
提示
:
出處
:
作法 : DP
此題與 d664. 11725 - Colorful Board 相同
/**********************************************************************************/
/* Problem: d572 "第六題:柏油我認識妳嗎之似曾不相識" from 板擦高中柏油杯inker出題、UVa改編*/
/* Language: C (1684 Bytes) */
/* Result: AC(280ms, 912KB) judge by this@ZeroJudge */
/* Author: morris1028 at 2011-09-15 16:18:52 */
/**********************************************************************************/
#include<stdio.h>
#include<string.h>
void change(int n, char *s) {
if(n == 0) return;
change(n/5, s+1);
*s = n%5;
}
int Calu(int n, char *s) {
if(n == 0) return 0;
return Calu(n-1, s+1)*5+(*s);
}
main() {
int T, n, m, K, x, y, C = 1;
int map[8][8], s5[10] = {1};
int i, j, k, l;
for(i = 1; i < 10; i++)
s5[i] = s5[i-1]*5;
scanf("%d", &T);
while(T--) {
scanf("%d %d", &m, &n);
scanf("%d", &K);
memset(map, 0, sizeof(map));
for(i = 0; i < K; i++) {
scanf("%d %d", &x, &y);
map[x][y] = 1;
}
m++, n++;
int last[78126], now[78126];
int state = s5[n]-1, tmp, now_state;
char CH[10];
memset(last, 0, sizeof(last));
last[0] = 1;
for(i = 0; i < m; i++) {
for(j = 1; j <= n; j++) {
for(k = 0; k <= state; k++) {
memset(CH, 0, sizeof(CH));
change(k, CH);
if(last[k] == 0) continue;
if(j != 1 && CH[j-2] == 0 && map[i+1][j-1] == 0) continue;
if(j != 1 && CH[j-2] != 0 && map[i+1][j-1] != 0) continue;
if(map[i+1][j]) {
CH[j-1] = 0;
now_state = Calu(n, CH);
now[now_state] = (now[now_state] + last[k])%1000000007;
} else {
for(l = 1; l <= 4; l++) {
if(CH[j-1] != l && (j == 1 || CH[j-2] != l)) {
tmp = CH[j-1], CH[j-1] = l;
now_state = Calu(n, CH);
now[now_state] = (now[now_state] + last[k])%1000000007;
CH[j-1] = tmp;
}
}
}
}
for(k = 0; k <= state; k++)
last[k] = now[k];
memset(now, 0, sizeof(now));
}
}
int Ans = 0;
for(i = 0; i <= state; i++)
Ans = (Ans+last[i])%1000000007;
printf("Case %d: %d\n", C++, Ans);
}
return 0;
}
上一篇:d650. 好多骰子
下一篇:a251. 假費波那契數