24h購物| | PChome| 登入
2013-08-23 20:23:58| 人氣3,697| 回應0 | 上一篇 | 下一篇

[UVA][dp] 1052 - Bit Compressor

推薦 0 收藏 0 轉貼0 訂閱站台

The aim of data compression is to reduce redundancy in stored or communicated data. This increases effective data density and speeds up data transfer rates. One possible method to compress any binary message is the following:

Replace any maximal sequence of n 1's with the binary version of n whenever it shortens the length of the message.

For example, the compressed form of the data 11111111001001111111111111110011 becomes 10000010011110011. The original data is 32 bits long while the compressed data is only 17 bits long.

The drawback of this method is that sometimes the decompression process yields more than one result for the original message, making it impossible to obtain the original message. Write a program that determines if the original message can be obtained from the compressed data when the length of the original message (L), the number of 1's in the original message (N) and the compressed data are given. The original message will be no longer than 16 Kbytes and the compressed data will be no longer than 40 bits.

Input 

The input file contains several test cases. Each test case has two lines. The first line contains L and N and the second line contains the compressed data.

The last case is followed by a line containing two zeroes.

Output 

For each test case, output a line containing the case number (starting with 1) and a message `YES', `NO' or `NOT UNIQUE'. `YES' means that the original message can be obtained. `NO' means that the compressed data has been corrupted and the original message cannot be obtained. `NOT UNIQUE' means that more than one message could have been the original message. Follow the format shown in the sample output.

Sample Input 

32 26 
10000010011110011 
9 7 
1010101 
14 14 
111111 
0 0

Sample Output 

Case #1: YES 
Case #2: NOT UNIQUE 
Case #3: NO

Claimer: The data used in this problem is unofficial data prepared by Derek Kisman. So any mistake here does not imply mistake in the offcial judge data. Only Derek Kisman is responsible for the mistakes. Report mistakes to dkisman@acm.org


原本的壓縮方式是將連續的 1 計數後,用一個二進制數表示。

現在要解壓縮,解壓縮的時候知道原本的長度,以及原本有多少個 1。

問解壓縮的可能有多少種。

特別小心當 0110 壓縮時仍是 0110。
也就是說 01110 也會壓縮成 0110。

那麼易想 dp 方程,dp[i][length][ones] = ways

i 表示 處理到解壓縮字串的第幾個。

必須考慮所有可能將 1 去作轉換,也就是要窮舉當前的 1 可能有多少要被釋放。

但是為了不違反原本的情況,不會同時存在連續兩段被釋放。

也就是說 101101, 不可以被解釋為 5 個 1 與 5 個 1。


#include <stdio.h>
#include <string.h>
#include <map>
#include <algorithm>
using namespace std;
map<int, int> dp[50][16*1025];
//dp[i][length][ones] = ways
int main() {
    freopen("in.txt","r+t",stdin);
    freopen("out.txt","w+t",stdout);
    int L, N;
    int i, j, k;
    int cases = 0;
    char s[105];
    while(scanf("%d %d", &L, &N) == 2 && L > 0) {
        scanf("%s", s);
        int len = strlen(s);
        for(i = 0; i <= len; i++) {
            for(j = 0; j <= L; j++)
                dp[i][j].clear();
        }
        dp[0][0][0] = 1;
        for(i = 0; i < len; i++) {
            if(s[i] == '0') {//appends a zero.
                for(j = 0; j < L; j++) {
                    for(map<int, int>::iterator it = dp[i][j].begin();
                        it != dp[i][j].end(); it++) {
                        dp[i+1][j+1][it->first] += it->second;
                    }
                }
            } else {
                int ones = 0;
                for(j = i; s[j]; j++) {
                    ones = (ones<<1) + s[j]-'0';
                    if(ones > N+2)    break;
                    if(s[j+1] != '1') {
                        if(ones != 2) {//10 -> X
                            for(k = 0; k < L; k++) {
                                if(k + ones > L)    break;
                                for(map<int, int>::iterator it = dp[i][k].begin();
                                    it != dp[i][k].end(); it++) {
                                    if(it->first + ones > N)    break;
                                    int &val = dp[j+1][k+ones][it->first + ones];
                                    val += it->second;
                                    if(val >= 2)    val = 2;
                                }
                            }
                        }
                        if(ones == 3) {//11 -> 11
                            ones = 2;
                            for(k = 0; k < L; k++) {
                                if(k + ones > L)    break;
                                for(map<int, int>::iterator it = dp[i][k].begin();
                                    it != dp[i][k].end(); it++) {
                                    if(it->first + ones > N)    break;
                                    int &val = dp[j+1][k+ones][it->first + ones];
                                    val += it->second;
                                    if(val >= 2)    val = 2;
                                }
                            }
                            ones = 3;
                        }
                    }
                }
            }
        }
        printf("Case #%d: ", ++cases);
        int ways = dp[len][L][N];
        if(ways == 1)
            puts("YES");
        else if(ways == 0)
            puts("NO");
        else
            puts("NOT UNIQUE");
    }
    return 0;
}/*
32 27
10000010011110011
3 3
11
2 2
11
2 1
10
15 9
0110000100100
11 7
0101010011
2 1
01
9 3
00011000
15 5
100010000001000
12 4
101000010100
20 10
110100000010011010
13 7
011001001000
18 8
100101001000010000
14 4
10101000000001
0 0
*/

台長: Morris
人氣(3,697) | 回應(0)| 推薦 (0)| 收藏 (0)| 轉寄
全站分類: 教育學習(進修、留學、學術研究、教育概況) | 個人分類: UVA |
此分類下一篇:[UVA][搜索bitmask] 10318 - Security Panel
此分類上一篇:[UVA] 710 - The Game

是 (若未登入"個人新聞台帳號"則看不到回覆唷!)
* 請輸入識別碼:
請輸入圖片中算式的結果(可能為0) 
(有*為必填)
TOP
詳全文